[
  {
    "path": ".gitignore",
    "content": ".idea\nout\n*.iml\n*.jar\nlib/\n*.zip\n**/target\n.bsp/\n"
  },
  {
    "path": ".scalafmt.conf",
    "content": ""
  },
  {
    "path": "LICENSE",
    "content": "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\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\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"
  },
  {
    "path": "README.md",
    "content": "Power Mode II Intellij plugin\n======================\n\n[![Join the chat at https://gitter.im/baptistemesta/power-mode-intellij-plugin](https://badges.gitter.im/baptistemesta/power-mode-intellij-plugin.svg)](https://gitter.im/baptistemesta/power-mode-intellij-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n![Demo](/images/powerMode.gif)\n\nInstallation\n--------------\n[Watch the Video](https://www.youtube.com/watch?v=aIWs7YQ9aMs)\n\n[Install from Jetbrains plugin repositories](https://plugins.jetbrains.com/plugin/8251)\n\nHow to use\n---------\n\nInstall the plugin then simply enable the sparkling in Preferences > Appearance > Power mode II\n\n## Features\n\n<ul>\n    <li>Exploding falling sparks</li>\n    <li>Editor shaking</li>\n    <li>Flames</li>\n    <li>Heatup based on typing speed. The more you type the more happens.</li>\n    <li>Keyboard shortcut to toggle power mode [shift ctrl alt O]</li>\n    <li>Choose particle colors and transparency within a color space</li>\n    <li>Adjust particle velocity and gravitation</li>\n    <li>Modify the animation frame rate</li>\n    <li>Multi caret support</li>\n    <li>Animation on caret movement</li>\n    <li>Play music folder: volume based on heatup</li>\n    <li>Play next song action: [shift ctrl alt M]</li>\n    <li>Visualize bigger file editing with \"BAM!\"</li>\n    <li>See your power level in the indicator box</li>\n    <li>Customizable animation images</li>\n    <li>Everything is configurable</li>\n</ul>\n\n<a href=\"https://github.com/axaluss/power-mode-intellij-plugin/releases/latest\"><img width=\"40\" src=\"https://raw.githubusercontent.com/axaluss/power-mode-intellij-plugin/master/images/download.png\"/>\nLatest Release Download</a>\n<br/>\n\n<a href=\"https://www.paypal.me/AlexanderThom\"><img style=\"width:100px; height: 100px;\" src=\"https://raw.githubusercontent.com/axaluss/power-mode-intellij-plugin/master/images/beer.png\"/>\nWant to Donate a Beer?</a>\n\n## Plugin Development Setup\n\n1. install scala intellij plugin\n2. import the sbt project (`build.sbt`)\n3. follow the docs [here](https://github.com/JetBrains/sbt-idea-plugin)\n4. create the plugin artifact `sbt packageArtifactZip`\n5. install in intellij\n\n## \"Architecture\"\n\n* `PowerMode` is the settings instance which is used by `PowerModeConfigurable` to populate the UI Settings dialog.\n  `PowerModeConfigurableUI` manages the settings dialog to change the settings in `PowerMode`.\n* `PowerMode` is stored/loaded by xml serializer and annotation magic by Intellij.\n* `PowerMode` starts up the `SparkContainerManager`. The `SparkContainerManager` creates a `SparkContainer` for each\n  editor.\n* The `SparkContainer` creates the `ElementOfPower` (`PowerSpark, PowerFlame`) and manages their animation and\n  lifecycle.\n\n### heatup\n\n* heatup increases the lifetime and amount of Sparks and Flames over time. The most values are multiplied\n  with `ElementOfPower.valueFactor` to simulate this heatup.\n  `ElementOfPower.valueFactor` is composed of `heatupFactor` (how much of all animation doesn't depend on heatup)\n  and `timeFactor` (how much heatup do we currently have).\n* The heatup itself is calculated by `keyStrokesPerMinute` and the amount of keystrokes within `heatupTime`.\n"
  },
  {
    "path": "build.sbt",
    "content": "import org.jetbrains.sbtidea.Keys._\n\nlazy val powerMode =\n  project\n    .in(file(\".\"))\n    .enablePlugins(SbtIdeaPlugin)\n    .settings(\n      version := \"105.501\",\n      scalaVersion := \"2.13.12\",\n      ThisBuild / intellijPluginName := \"Power Mode II\",\n      ThisBuild / intellijBuild := \"232.10227.8\",\n      ThisBuild / intellijPlatform := IntelliJPlatform.IdeaCommunity,\n      Global / intellijAttachSources := true,\n      Compile / javacOptions ++= \"--release\" :: \"17\" :: Nil,\n      intellijPlugins += \"com.intellij.properties\".toPlugin,\n      libraryDependencies ++= Seq(\n        \"javazoom\" % \"jlayer\" % \"1.0.1\",\n        \"org.typelevel\" %% \"squants\" % \"1.6.0\",\n        \"org.apache.commons\" % \"commons-math3\" % \"3.3\",\n        \"com.eclipsesource.minimal-json\" % \"minimal-json\" % \"0.9.5\" withSources ()\n      ),\n      libraryDependencies += \"com.ryanstull\" %% \"scalanullsafe\" % \"1.2.6\",\n      scalacOptions in ThisBuild += \"-deprecation\",\n      unmanagedJars in Compile += baseDirectory.value / \"lib\",\n      unmanagedResourceDirectories in Compile += baseDirectory.value / \"resources\",\n      resourceDirectories in Runtime += baseDirectory.value / \"resources\",\n      unmanagedResourceDirectories in Test += baseDirectory.value / \"testResources\",\n      packageMethod := PackagingMethod.Standalone(),\n      bundleScalaLibrary in ThisBuild := true\n    )\n"
  },
  {
    "path": "log4j.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n\n<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\">\n    <appender name=\"console\" class=\"org.apache.log4j.ConsoleAppender\">\n        <param name=\"Target\" value=\"System.out\"/>\n        <layout class=\"org.apache.log4j.PatternLayout\">\n            <param name=\"ConversionPattern\" value=\"[%p] %c %M - %m%n\"/>\n        </layout>\n    </appender>\n\n    <category name=\"de.ax.powermode\">\n        <priority value=\"trace\"/>\n        <appender-ref ref=\"console\"/>\n    </category>\n\n    <category name=\"com.intellij\">\n        <priority value=\"info\"/>\n        <appender-ref ref=\"console\"/>\n    </category>\n\n\n</log4j:configuration>"
  },
  {
    "path": "project/build.properties",
    "content": "sbt.version=1.4.3\n"
  },
  {
    "path": "project/plugins.sbt",
    "content": "addSbtPlugin(\"org.jetbrains\" % \"sbt-idea-plugin\" % \"3.18.3\")\n"
  },
  {
    "path": "resources/META-INF/plugin.xml",
    "content": "<idea-plugin>\n    <id>de.ax.powermode</id>\n    <name>Power Mode II</name>\n    <version>105.501</version>\n    <vendor email=\"axaluss@gmail.com\" url=\"https://github.com/axaluss/power-mode-intellij-plugin\">Alexander Thom\n    </vendor>\n    <description><![CDATA[\n        <h1>Power Mode</h1>\n        <span>Based on the activate-power-mode atom plugin and forked from Baptiste Mesta on Github.</span>\n        <h2>Features</h2>\n        <ul>\n            <li>Exploding falling sparks</li>\n            <li>Editor shaking</li>\n            <li>Flames</li>\n            <li>Heatup based on typing speed. The more you type the more happens.</li>\n            <li>Keyboard shortcut to toggle power mode [shift ctrl alt O]</li>\n            <li>Choose particle colors and transparency within a color space</li>\n            <li>Adjust particle velocity and gravitation</li>\n            <li>Modify the animation frame rate</li>\n            <li>Multi caret support</li>\n            <li>Animation on caret movement</li>\n            <li>Play music folder: volume based on heatup</li>\n            <li>Play next song action: [shift ctrl alt M]</li>\n            <li>Visualize bigger file editing with \"BAM!\"</li>\n            <li>See your power level in the indicator box</li>\n            <li>Customizable animation images</li>\n            <li>Everything is configurable</li>\n        </ul>\n        <h2>Usage</h2>\n        <ol>\n            <li>Install the plugin</li>\n            <li>ENTER POWER MODE in Preferences > Appearance > Power mode II</li>\n            <li>CHANGE THE SLIDERS and options to your liking</li>\n        </ol>\n\n        <a href=\"https://github.com/axaluss/power-mode-intellij-plugin/releases/latest\"><img\n                width=\"40\"\n                src=\"https://raw.githubusercontent.com/axaluss/power-mode-intellij-plugin/master/images/download.png\"/>\n            Latest Release Download</a>\n        <br/>\n<h2>latest changes </h2>\nfixes\n <ul>\n    <li>#67 hashCode NPE</li>\n    <li>#64 Framerate settings is always set to default</li>\n    <li>#65 Not compatible with the version IntelliJ IDEA 2023.2.3</li>\n    <li>#66 hold references to disposed objects</li>\n    <li>#60 When enabled, inline git diff is not clickable</li>\n</ul>\n        <a href=\"https://www.paypal.me/AlexanderThom\">\n            <img style=\"width:100px; height: 100px;\"\n                 src=\"https://raw.githubusercontent.com/axaluss/power-mode-intellij-plugin/master/images/beer.png\"/>\n            Want to pass me a Beer?\n        </a>\n        ]]></description>\n\n    <idea-version since-build=\"232\"/>\n\n    <depends>com.intellij.modules.platform</depends>\n\n\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <applicationConfigurable groupId=\"appearance\" groupWeight=\"20\" id=\"power.mode.ii\" displayName=\"Power Mode II\"\n                                 instance=\"de.ax.powermode.PowerModeConfigurable\"/>\n        <applicationService serviceImplementation=\"de.ax.powermode.PowerMode\"/>\n    </extensions>\n\n    <applicationListeners>\n        <listener class=\"de.ax.powermode.PowerModeStartup\" topic=\"com.intellij.ide.AppLifecycleListener\"/>\n    </applicationListeners>\n\n    <actions>\n\n        <action id=\"togglePowerModeII\" class=\"de.ax.powermode.TogglePowerMode\" text=\"Toggle Power Mode II\"\n                description=\"Toggle Power Mode II\">\n            <add-to-group group-id=\"ToolsMenu\" anchor=\"last\"/>\n            <keyboard-shortcut keymap=\"$default\" first-keystroke=\"shift ctrl alt O\"/>\n        </action>\n        <action id=\"powerModeIInextSong\" class=\"de.ax.powermode.NextSongAction\" text=\"next Power Mode song\"\n                description=\"next Power Mode song\">\n            <add-to-group group-id=\"ToolsMenu\" anchor=\"last\"/>\n            <keyboard-shortcut keymap=\"$default\" first-keystroke=\"shift ctrl alt M\"/>\n        </action>\n    </actions>\n\n</idea-plugin>"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/ColorViewController.java",
    "content": "package de.ax.powermode.power.color;\n\nimport de.ax.powermode.PowerMode;\n\n/**\n * Created by nyxos on 05.07.16.\n */\npublic class ColorViewController {\n    private final PowerMode powerMode;\n    double c = 0;\n    double f = 60.0;\n    //    double x = (255 / 5000.0) * f;\n    int dir = 1;\n\n    public double genX() {\n        return dir * ((powerMode.getBlueTo() - powerMode.getBlueFrom()) / 5000.0) * f;\n    }\n\n    public ColorViewController(MultiGradientPanel colorView, PowerMode powerMode) {\n        this.powerMode = powerMode;\n        Thread thread = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (colorView.isVisible()) {\n                    long t0 = System.currentTimeMillis();\n                    c = Math.max(Math.min((c + genX()), powerMode.blueTo()), powerMode.blueFrom());\n                    if (c >= powerMode.blueTo()) {\n                        c = powerMode.blueTo();\n                        dir *= -1;\n                    }\n                    if (c <= powerMode.blueFrom()) {\n                        c = powerMode.blueFrom();\n                        dir *= -1;\n                    }\n                    colorView.doUpdate(c);\n                    colorView.repaint();\n                    try {\n                        Thread.sleep((long) (Math.max(0, (1000 / f) - (System.currentTimeMillis() - t0))));\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        });\n        thread.start();\n    }\n}\n"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/MultiGradientPanel.java",
    "content": "package de.ax.powermode.power.color;\n\nimport javax.swing.*;\nimport java.awt.*;\nimport java.awt.geom.Point2D;\n\n\npublic class MultiGradientPanel extends JPanel {\n    int size;\n\n    public void setColorEdges(ColorEdges colorEdges) {\n        this.colorEdges = colorEdges;\n    }\n\n    private ColorEdges colorEdges;\n\n\n    public MultiGradientPanel(int size, ColorEdges colorEdges) {\n        super();\n        this.size = size;\n        this.colorEdges = colorEdges;\n        this.setPreferredSize(new Dimension(size, size));\n    }\n\n\n    @Override\n    protected void paintComponent(Graphics g) {\n        super.paintComponent(g);\n        Graphics2D g2d = (Graphics2D) g;\n        GradientPaint twoColorGradient = new GradientPaint(\n                size, 0f, colorEdges.getRightTop(), 0, size, colorEdges.getLeftBottom());\n\n        float radius = size - (size / 4.0f);\n        float[] dist = {0f, 1.0f};\n        Point2D center = new Point2D.Float(0f, 0f);\n        Color noColor = new Color(0f, 0f, 0f, 0f);\n        Color[] colors = {colorEdges.getLeftTop(), noColor};\n        RadialGradientPaint thirdColor = new RadialGradientPaint(center, radius, dist, colors);\n\n\n        center = new Point2D.Float(size, size);\n        Color[] colors2 = {colorEdges.getRightBottom(), noColor};\n        RadialGradientPaint fourthColor = new RadialGradientPaint(center, radius, dist, colors2);\n\n        g2d.setPaint(twoColorGradient);\n        g2d.fillRect(0, 0, size, size);\n\n        g2d.setPaint(thirdColor);\n        g2d.fillRect(0, 0, size, size);\n\n        g2d.setPaint(fourthColor);\n        g2d.fillRect(0, 0, size, size);\n    }\n\n    public void doUpdate(double c) {\n        int c1 = (int) c;\n        colorEdges.updateColors(c1);\n    }\n\n\n}"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/UiTest.form",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class=\"de.ax.powermode.power.color.UiTest\">\n  <grid id=\"27dc6\" binding=\"root\" layout-manager=\"BorderLayout\" hgap=\"0\" vgap=\"0\">\n    <constraints>\n      <xy x=\"20\" y=\"20\" width=\"500\" height=\"400\"/>\n    </constraints>\n    <properties/>\n    <border type=\"none\"/>\n    <children>\n      <grid id=\"c9691\" binding=\"colorView\" custom-create=\"true\" layout-manager=\"GridLayoutManager\" row-count=\"1\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n        <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n        <constraints border-constraint=\"Center\"/>\n        <properties/>\n        <border type=\"none\"/>\n        <children/>\n      </grid>\n    </children>\n  </grid>\n</form>\n"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/UiTest.java",
    "content": "package de.ax.powermode.power.color;\n\nimport javax.swing.*;\nimport java.awt.*;\n\n/**\n * Created by nyxos on 21.06.16.\n */\npublic class UiTest {\n    private JPanel colorView;\n    private JPanel root;\n\n\n    static double c = 0;\n    static double f = 60.0;\n    static double x = (255 / 5000.0) * f;\n\n    public static void main(String[] args) {\n        JFrame frame = new JFrame(\"UiTest\");\n        UiTest uiTest = new UiTest();\n        frame.setContentPane(uiTest.root);\n        frame.setSize(500, 500);\n\n        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n        frame.pack();\n        frame.setVisible(true);\n\n\n    }\n\n    private void createUIComponents() {\n//        colorView = new MultiGradientPanel(500, new ColorEdges());\n//        new ColorViewController((MultiGradientPanel) colorView);\n    }\n\n    {\n// GUI initializer generated by IntelliJ IDEA GUI Designer\n// >>> IMPORTANT!! <<<\n// DO NOT EDIT OR ADD ANY CODE HERE!\n        $$$setupUI$$$();\n    }\n\n    /**\n     * Method generated by IntelliJ IDEA GUI Designer\n     * >>> IMPORTANT!! <<<\n     * DO NOT edit this method OR call it in your code!\n     *\n     * @noinspection ALL\n     */\n    private void $$$setupUI$$$() {\n        createUIComponents();\n        root = new JPanel();\n        root.setLayout(new BorderLayout(0, 0));\n        root.add(colorView, BorderLayout.CENTER);\n    }\n\n    /**\n     * @noinspection ALL\n     */\n    public JComponent $$$getRootComponent$$$() {\n        return root;\n    }\n}\n"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.form",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class=\"de.ax.powermode.power.ui.PowerModeConfigurableUI\">\n  <grid id=\"263a9\" binding=\"mainPanel\" layout-manager=\"GridLayoutManager\" row-count=\"2\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n    <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n    <constraints>\n      <xy x=\"20\" y=\"-118\" width=\"1091\" height=\"1173\"/>\n    </constraints>\n    <properties/>\n    <border type=\"none\"/>\n    <children>\n      <tabbedpane id=\"2ab37\">\n        <constraints>\n          <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\">\n            <preferred-size width=\"200\" height=\"200\"/>\n          </grid>\n        </constraints>\n        <properties>\n          <tabLayoutPolicy value=\"0\"/>\n        </properties>\n        <border type=\"none\"/>\n        <children>\n          <grid id=\"c9d96\" layout-manager=\"GridLayoutManager\" row-count=\"2\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n            <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n            <constraints>\n              <tabbedpane title=\"GENERAL OPTIONS\"/>\n            </constraints>\n            <properties/>\n            <border type=\"none\"/>\n            <children>\n              <scrollpane id=\"59a36\">\n                <constraints>\n                  <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"7\" hsize-policy=\"7\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\"/>\n                </constraints>\n                <properties>\n                  <enabled value=\"true\"/>\n                </properties>\n                <border type=\"none\"/>\n                <children>\n                  <grid id=\"27dc6\" layout-manager=\"GridLayoutManager\" row-count=\"19\" column-count=\"3\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n                    <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n                    <constraints/>\n                    <properties/>\n                    <border type=\"none\"/>\n                    <children>\n                      <component id=\"c1982\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"18\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"framerate\"/>\n                          <toolTipText value=\"particle &amp; flame updates per second\"/>\n                        </properties>\n                      </component>\n                      <component id=\"43211\" class=\"javax.swing.JLabel\" binding=\"frameRateValue\">\n                        <constraints>\n                          <grid row=\"18\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"ddd7e\" class=\"javax.swing.JSlider\" binding=\"frameRate\">\n                        <constraints>\n                          <grid row=\"18\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"120\"/>\n                          <minimum value=\"5\"/>\n                          <value value=\"30\"/>\n                        </properties>\n                      </component>\n                      <component id=\"2467a\" class=\"javax.swing.JCheckBox\" binding=\"powerModeEnabled\">\n                        <constraints>\n                          <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"ENTER POWER MODE!\"/>\n                        </properties>\n                      </component>\n                      <component id=\"685dd\" class=\"javax.swing.JCheckBox\" binding=\"PARTICLESCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"SPARKS!\"/>\n                        </properties>\n                      </component>\n                      <component id=\"81466\" class=\"javax.swing.JCheckBox\" binding=\"shakeEnabled\">\n                        <constraints>\n                          <grid row=\"2\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"SHAKE!\"/>\n                        </properties>\n                      </component>\n                      <component id=\"221d1\" class=\"javax.swing.JCheckBox\" binding=\"FLAMESCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"3\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"FLAMES!\"/>\n                        </properties>\n                      </component>\n                      <component id=\"97367\" class=\"javax.swing.JCheckBox\" binding=\"visualizeEveryCaretMovementCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"4\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"VISUALIZE EVERY CARET MOVEMENT!\"/>\n                          <toolTipText value=\"When disabled: only typing of letters will cause effects.&#10;When enabled: every caret movement will cause effects.\" noi18n=\"true\"/>\n                        </properties>\n                      </component>\n                      <component id=\"1f2a3\" class=\"javax.swing.JCheckBox\" binding=\"PLAYMUSICCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"8\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"PLAY MUSIC\"/>\n                          <toolTipText value=\"next song: shift ctrl alt M\"/>\n                        </properties>\n                      </component>\n                      <component id=\"d851e\" class=\"javax.swing.JTextField\" binding=\"soundsFolder\">\n                        <constraints>\n                          <grid row=\"8\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"150\" height=\"-1\"/>\n                          </grid>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"f7cb8\" class=\"javax.swing.JCheckBox\" binding=\"BAMCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"5\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"BAM!\"/>\n                          <toolTipText value=\"visualize document changes with BAM!\"/>\n                        </properties>\n                      </component>\n                      <component id=\"4bca3\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"15\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"BAM! life [ms]\"/>\n                        </properties>\n                      </component>\n                      <component id=\"794d8\" class=\"javax.swing.JLabel\" binding=\"bamLifeValue\">\n                        <constraints>\n                          <grid row=\"15\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"f621e\" class=\"javax.swing.JSlider\" binding=\"bamLife\">\n                        <constraints>\n                          <grid row=\"15\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10000\"/>\n                        </properties>\n                      </component>\n                      <component id=\"16478\" class=\"javax.swing.JCheckBox\" binding=\"PowerIndicatorCheckBox\">\n                        <constraints>\n                          <grid row=\"7\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"POWER INDICATOR!\"/>\n                          <toolTipText value=\"Displays an imprecise visualization of the current heatup value.\"/>\n                        </properties>\n                      </component>\n                      <component id=\"2456b\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"9\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"shake range [px]\"/>\n                          <toolTipText value=\"how many pixels should the shaking move?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"fbfcb\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"10\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"min volume %\"/>\n                          <toolTipText value=\"how many pixels should the shaking move?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"1246c\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"11\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"max volume %\"/>\n                          <toolTipText value=\"how many pixels should the shaking move?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"a35ff\" class=\"javax.swing.JLabel\" binding=\"shakeRangeValue\">\n                        <constraints>\n                          <grid row=\"9\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"a2ce9\" class=\"javax.swing.JLabel\" binding=\"minVolumeValue\">\n                        <constraints>\n                          <grid row=\"10\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"4f3d8\" class=\"javax.swing.JLabel\" binding=\"maxVolumeValue\">\n                        <constraints>\n                          <grid row=\"11\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"d66bd\" class=\"javax.swing.JSlider\" binding=\"shakeRange\">\n                        <constraints>\n                          <grid row=\"9\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"5b124\" class=\"javax.swing.JSlider\" binding=\"minVolume\">\n                        <constraints>\n                          <grid row=\"10\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"e3988\" class=\"javax.swing.JSlider\" binding=\"maxVolume\">\n                        <constraints>\n                          <grid row=\"11\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"72e7\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"12\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"max flame size [px]\"/>\n                          <toolTipText value=\"maximum flame size in pixels\"/>\n                        </properties>\n                      </component>\n                      <component id=\"afddc\" class=\"javax.swing.JLabel\" binding=\"maxFlameSizeValue\">\n                        <constraints>\n                          <grid row=\"12\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"acbf8\" class=\"javax.swing.JSlider\" binding=\"maxFlameSize\">\n                        <constraints>\n                          <grid row=\"12\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"500\"/>\n                        </properties>\n                      </component>\n                      <component id=\"74982\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"13\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"flame life [ms]\"/>\n                          <toolTipText value=\"time to live for a flame in milliseconds\"/>\n                        </properties>\n                      </component>\n                      <component id=\"badbb\" class=\"javax.swing.JLabel\" binding=\"flameLifeValue\">\n                        <constraints>\n                          <grid row=\"13\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"321e2\" class=\"javax.swing.JSlider\" binding=\"flameLife\">\n                        <constraints>\n                          <grid row=\"13\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10000\"/>\n                        </properties>\n                      </component>\n                      <component id=\"4ae70\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"7\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"hint: 'heatup base level' should be &lt;100%\"/>\n                        </properties>\n                      </component>\n                      <component id=\"ae24c\" class=\"javax.swing.JCheckBox\" binding=\"customFlameImages\">\n                        <constraints>\n                          <grid row=\"14\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"custom flame images\"/>\n                          <toolTipText value=\"provide a folder with the images of a flame animation\"/>\n                        </properties>\n                      </component>\n                      <component id=\"f9586\" class=\"javax.swing.JTextField\" binding=\"flameImagesFolder\">\n                        <constraints>\n                          <grid row=\"14\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"150\" height=\"-1\"/>\n                          </grid>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"b4da3\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"14\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"image folder:\"/>\n                        </properties>\n                      </component>\n                      <component id=\"b011a\" class=\"javax.swing.JCheckBox\" binding=\"customBamImages\">\n                        <constraints>\n                          <grid row=\"16\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"custom BAM! images\"/>\n                          <toolTipText value=\"choose your own BAM! images\"/>\n                        </properties>\n                      </component>\n                      <component id=\"30044\" class=\"javax.swing.JCheckBox\" binding=\"animateBAMImagesCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"17\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"animate BAM! images\"/>\n                          <toolTipText value=\"will cycle through all BAM! images in the given folder and create an animation (like a GIF).\"/>\n                        </properties>\n                      </component>\n                      <component id=\"31962\" class=\"javax.swing.JTextField\" binding=\"bamImagesFolder\">\n                        <constraints>\n                          <grid row=\"16\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"150\" height=\"-1\"/>\n                          </grid>\n                        </constraints>\n                        <properties/>\n                      </component>\n                      <component id=\"ebfd1\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"16\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"image folder:\"/>\n                        </properties>\n                      </component>\n                      <component id=\"1304a\" class=\"javax.swing.JCheckBox\" binding=\"HOTKEYHEATUPCheckBox\" default-binding=\"true\">\n                        <constraints>\n                          <grid row=\"6\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"3\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"HOTKEY HEATUP\"/>\n                          <toolTipText value=\"Disable if having problems with hotkey visualization\"/>\n                        </properties>\n                      </component>\n                      <component id=\"452c\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"2\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"!!! might interfere with autocompletion and other plugins/editors!\" noi18n=\"true\"/>\n                        </properties>\n                      </component>\n                      <component id=\"64868\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"8\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"music folder:\"/>\n                        </properties>\n                      </component>\n                    </children>\n                  </grid>\n                </children>\n              </scrollpane>\n              <vspacer id=\"e124f\">\n                <constraints>\n                  <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" indent=\"0\" use-parent-layout=\"false\"/>\n                </constraints>\n              </vspacer>\n            </children>\n          </grid>\n          <scrollpane id=\"23fd3\">\n            <constraints>\n              <tabbedpane title=\"HEATUP\"/>\n            </constraints>\n            <properties/>\n            <border type=\"none\"/>\n            <children>\n              <grid id=\"30a31\" layout-manager=\"GridLayoutManager\" row-count=\"6\" column-count=\"3\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n                <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n                <constraints/>\n                <properties/>\n                <border type=\"none\" title=\"Heatup\"/>\n                <children>\n                  <component id=\"81202\" class=\"javax.swing.JLabel\">\n                    <constraints>\n                      <grid row=\"3\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"176\" height=\"15\"/>\n                      </grid>\n                    </constraints>\n                    <properties>\n                      <text value=\"heatup base level [%]\"/>\n                      <toolTipText value=\"the lower the level the fewer happens at the start of typing.\"/>\n                    </properties>\n                  </component>\n                  <component id=\"bc55\" class=\"javax.swing.JLabel\" binding=\"heatupValue\">\n                    <constraints>\n                      <grid row=\"3\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <text value=\"Label\"/>\n                    </properties>\n                  </component>\n                  <component id=\"50558\" class=\"javax.swing.JSlider\" binding=\"heatup\">\n                    <constraints>\n                      <grid row=\"3\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties/>\n                  </component>\n                  <component id=\"4cf47\" class=\"javax.swing.JLabel\">\n                    <constraints>\n                      <grid row=\"4\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"176\" height=\"15\"/>\n                      </grid>\n                    </constraints>\n                    <properties>\n                      <text value=\"heatup time [ms]\"/>\n                      <toolTipText value=\"time range in milliseconds. The count of keystrokes in this period is used to calculate heatup.\"/>\n                    </properties>\n                  </component>\n                  <component id=\"addf7\" class=\"javax.swing.JLabel\" binding=\"heatupTimeValue\">\n                    <constraints>\n                      <grid row=\"4\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <text value=\"Label\"/>\n                    </properties>\n                  </component>\n                  <component id=\"266a0\" class=\"javax.swing.JSlider\" binding=\"heatupTime\">\n                    <constraints>\n                      <grid row=\"4\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <maximum value=\"60000\"/>\n                    </properties>\n                  </component>\n                  <component id=\"88552\" class=\"javax.swing.JLabel\">\n                    <constraints>\n                      <grid row=\"2\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"176\" height=\"15\"/>\n                      </grid>\n                    </constraints>\n                    <properties>\n                      <text value=\"heatup threshold [%]\"/>\n                      <toolTipText value=\"how much heatup in % has to be reached until something happens\"/>\n                    </properties>\n                  </component>\n                  <component id=\"b9417\" class=\"javax.swing.JLabel\" binding=\"heatupThresholdValue\">\n                    <constraints>\n                      <grid row=\"2\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <text value=\"Label\"/>\n                    </properties>\n                  </component>\n                  <component id=\"df601\" class=\"javax.swing.JSlider\" binding=\"heatupThreshold\">\n                    <constraints>\n                      <grid row=\"2\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <maximum value=\"100\"/>\n                      <minimum value=\"0\"/>\n                      <value value=\"30\"/>\n                    </properties>\n                  </component>\n                  <component id=\"e564c\" class=\"javax.swing.JLabel\">\n                    <constraints>\n                      <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"176\" height=\"15\"/>\n                      </grid>\n                    </constraints>\n                    <properties>\n                      <text value=\"keystrokes per minute\"/>\n                      <toolTipText value=\"used to calculate heatup\"/>\n                    </properties>\n                  </component>\n                  <component id=\"7cba5\" class=\"javax.swing.JLabel\" binding=\"keyStrokesPerMinuteValue\">\n                    <constraints>\n                      <grid row=\"1\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <text value=\"Label\"/>\n                    </properties>\n                  </component>\n                  <component id=\"5af3\" class=\"javax.swing.JSlider\" binding=\"keyStrokesPerMinute\">\n                    <constraints>\n                      <grid row=\"1\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                    <properties>\n                      <maximum value=\"3000\"/>\n                      <value value=\"100\"/>\n                    </properties>\n                  </component>\n                  <component id=\"d3a6d\" class=\"javax.swing.JTextArea\">\n                    <constraints>\n                      <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"3\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"150\" height=\"50\"/>\n                      </grid>\n                    </constraints>\n                    <properties>\n                      <editable value=\"false\"/>\n                      <enabled value=\"true\"/>\n                      <text value=\"Heatup is the dynamic power factor in % which defines how much&#10; sparkling and fire is happening. &#10;Its calculated by 'keystrokes per minute' constant, &#10;the 'heatup time'- window and how much typing and hotkeying is done within that time window.&#10;'heatup base level' is the minimum heatup that is always active. &#10;'heatup threshold' is the minimum heatup required such that things start happening.&#10;&#10;\" noi18n=\"true\"/>\n                    </properties>\n                  </component>\n                  <vspacer id=\"87d17\">\n                    <constraints>\n                      <grid row=\"5\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                  </vspacer>\n                </children>\n              </grid>\n            </children>\n          </scrollpane>\n          <scrollpane id=\"8994b\">\n            <constraints>\n              <tabbedpane title=\"SPARKS\"/>\n            </constraints>\n            <properties/>\n            <border type=\"none\"/>\n            <children>\n              <grid id=\"eed8f\" layout-manager=\"GridLayoutManager\" row-count=\"2\" column-count=\"1\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n                <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n                <constraints/>\n                <properties/>\n                <border type=\"none\"/>\n                <children>\n                  <grid id=\"40358\" layout-manager=\"GridLayoutManager\" row-count=\"16\" column-count=\"3\" same-size-horizontally=\"false\" same-size-vertically=\"false\" hgap=\"-1\" vgap=\"-1\">\n                    <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n                    <constraints>\n                      <grid row=\"0\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\">\n                        <preferred-size width=\"200\" height=\"245\"/>\n                      </grid>\n                    </constraints>\n                    <properties/>\n                    <border type=\"none\" title=\"Sparks\"/>\n                    <children>\n                      <component id=\"f3691\" class=\"javax.swing.JLabel\" binding=\"sparkColorRedFromValue\">\n                        <constraints>\n                          <grid row=\"1\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"31348\" class=\"javax.swing.JSlider\" binding=\"sparkColorRedFrom\">\n                        <constraints>\n                          <grid row=\"1\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <grid id=\"d0f3a\" binding=\"colorView\" custom-create=\"true\" layout-manager=\"GridLayoutManager\" row-count=\"1\" column-count=\"1\" same-size-horizontally=\"true\" same-size-vertically=\"true\" hgap=\"-1\" vgap=\"-1\">\n                        <margin top=\"0\" left=\"0\" bottom=\"0\" right=\"0\"/>\n                        <constraints>\n                          <grid row=\"0\" column=\"0\" row-span=\"11\" col-span=\"1\" vsize-policy=\"3\" hsize-policy=\"3\" anchor=\"0\" fill=\"3\" indent=\"0\" use-parent-layout=\"false\">\n                            <minimum-size width=\"200\" height=\"200\"/>\n                            <preferred-size width=\"200\" height=\"200\"/>\n                            <maximum-size width=\"200\" height=\"200\"/>\n                          </grid>\n                        </constraints>\n                        <properties/>\n                        <border type=\"none\"/>\n                        <children/>\n                      </grid>\n                      <component id=\"d622e\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"0\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"136\" height=\"14\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark color red range\"/>\n                          <toolTipText value=\"how many sparks should appear?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"941fc\" class=\"javax.swing.JLabel\" binding=\"sparkColorRedToValue\">\n                        <constraints>\n                          <grid row=\"2\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"786cb\" class=\"javax.swing.JSlider\" binding=\"sparkColorRedTo\">\n                        <constraints>\n                          <grid row=\"2\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"21559\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"3\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark color green range\"/>\n                          <toolTipText value=\"how many sparks should appear?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"e4b78\" class=\"javax.swing.JLabel\" binding=\"sparkColorGreenFromValue\">\n                        <constraints>\n                          <grid row=\"4\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"81e87\" class=\"javax.swing.JSlider\" binding=\"sparkColorGreenFrom\">\n                        <constraints>\n                          <grid row=\"4\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"b5faf\" class=\"javax.swing.JLabel\" binding=\"sparkColorGreenToValue\">\n                        <constraints>\n                          <grid row=\"5\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"ddc3c\" class=\"javax.swing.JSlider\" binding=\"sparkColorGreenTo\">\n                        <constraints>\n                          <grid row=\"5\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"3e35c\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"6\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark color blue range\"/>\n                          <toolTipText value=\"how many sparks should appear?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"30786\" class=\"javax.swing.JLabel\" binding=\"sparkColorBlueFromValue\">\n                        <constraints>\n                          <grid row=\"7\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"cbe45\" class=\"javax.swing.JSlider\" binding=\"sparkColorBlueFrom\">\n                        <constraints>\n                          <grid row=\"7\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"d73f\" class=\"javax.swing.JLabel\" binding=\"sparkColorBlueToValue\">\n                        <constraints>\n                          <grid row=\"8\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"91c\" class=\"javax.swing.JSlider\" binding=\"sparkColorBlueTo\">\n                        <constraints>\n                          <grid row=\"8\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"6e81a\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"9\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"alpha\"/>\n                        </properties>\n                      </component>\n                      <component id=\"f8276\" class=\"javax.swing.JLabel\" binding=\"sparkColorAlphaValue\">\n                        <constraints>\n                          <grid row=\"10\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"5402\" class=\"javax.swing.JSlider\" binding=\"sparkColorAlpha\">\n                        <constraints>\n                          <grid row=\"10\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"255\"/>\n                        </properties>\n                      </component>\n                      <component id=\"2632e\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"11\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark count\"/>\n                          <toolTipText value=\"how many sparks should appear?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"3b9ad\" class=\"javax.swing.JLabel\" binding=\"sparkCountValue\">\n                        <constraints>\n                          <grid row=\"11\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"90a0\" class=\"javax.swing.JSlider\" binding=\"sparkCount\">\n                        <constraints>\n                          <grid row=\"11\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"100\"/>\n                        </properties>\n                      </component>\n                      <component id=\"cd69f\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"12\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark life [ms]\"/>\n                          <toolTipText value=\"how many milliseconds should a spark live?\"/>\n                        </properties>\n                      </component>\n                      <component id=\"f5c2a\" class=\"javax.swing.JLabel\" binding=\"sparkLifeValue\">\n                        <constraints>\n                          <grid row=\"12\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"4f7ba\" class=\"javax.swing.JSlider\" binding=\"sparkLife\">\n                        <constraints>\n                          <grid row=\"12\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10000\"/>\n                        </properties>\n                      </component>\n                      <component id=\"1b40f\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"13\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark size [px]\"/>\n                          <toolTipText value=\"spark size in pixels\"/>\n                        </properties>\n                      </component>\n                      <component id=\"b1591\" class=\"javax.swing.JLabel\" binding=\"sparkSizeValue\">\n                        <constraints>\n                          <grid row=\"13\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"ded61\" class=\"javax.swing.JSlider\" binding=\"sparkSize\">\n                        <constraints>\n                          <grid row=\"13\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10\"/>\n                        </properties>\n                      </component>\n                      <component id=\"c5412\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"14\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark velocity factor %\"/>\n                          <toolTipText value=\"100% is default spark velocity\"/>\n                        </properties>\n                      </component>\n                      <component id=\"c7259\" class=\"javax.swing.JLabel\" binding=\"velocityFactorValue\">\n                        <constraints>\n                          <grid row=\"14\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"efd58\" class=\"javax.swing.JSlider\" binding=\"velocityFactor\">\n                        <constraints>\n                          <grid row=\"14\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10000\"/>\n                          <minimum value=\"-10000\"/>\n                          <value value=\"100\"/>\n                        </properties>\n                      </component>\n                      <component id=\"3a93a\" class=\"javax.swing.JLabel\">\n                        <constraints>\n                          <grid row=\"15\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\">\n                            <preferred-size width=\"176\" height=\"15\"/>\n                          </grid>\n                        </constraints>\n                        <properties>\n                          <text value=\"spark gravity factor %\"/>\n                          <toolTipText value=\"100% is default spark gravity\"/>\n                        </properties>\n                      </component>\n                      <component id=\"5b27f\" class=\"javax.swing.JLabel\" binding=\"gravityFactorValue\">\n                        <constraints>\n                          <grid row=\"15\" column=\"1\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"0\" anchor=\"8\" fill=\"0\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <text value=\"Label\"/>\n                        </properties>\n                      </component>\n                      <component id=\"108ab\" class=\"javax.swing.JSlider\" binding=\"gravityFactor\">\n                        <constraints>\n                          <grid row=\"15\" column=\"2\" row-span=\"1\" col-span=\"1\" vsize-policy=\"0\" hsize-policy=\"6\" anchor=\"8\" fill=\"1\" indent=\"0\" use-parent-layout=\"false\"/>\n                        </constraints>\n                        <properties>\n                          <maximum value=\"10000\"/>\n                          <minimum value=\"-10000\"/>\n                          <value value=\"100\"/>\n                        </properties>\n                      </component>\n                    </children>\n                  </grid>\n                  <vspacer id=\"11a93\">\n                    <constraints>\n                      <grid row=\"1\" column=\"0\" row-span=\"1\" col-span=\"1\" vsize-policy=\"6\" hsize-policy=\"1\" anchor=\"0\" fill=\"2\" indent=\"0\" use-parent-layout=\"false\"/>\n                    </constraints>\n                  </vspacer>\n                </children>\n              </grid>\n            </children>\n          </scrollpane>\n        </children>\n      </tabbedpane>\n    </children>\n  </grid>\n</form>\n"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.java",
    "content": "package de.ax.powermode.power.ui;\n\nimport com.intellij.openapi.options.ConfigurableUi;\nimport com.intellij.openapi.options.ConfigurationException;\nimport com.intellij.uiDesigner.core.GridConstraints;\nimport com.intellij.uiDesigner.core.GridLayoutManager;\nimport com.intellij.uiDesigner.core.Spacer;\nimport de.ax.powermode.PowerMode;\nimport de.ax.powermode.power.color.ColorViewController;\nimport de.ax.powermode.power.color.MultiGradientPanel;\n\nimport javax.swing.*;\nimport javax.swing.border.TitledBorder;\nimport javax.swing.event.ChangeEvent;\nimport javax.swing.event.ChangeListener;\nimport javax.swing.event.DocumentEvent;\nimport javax.swing.event.DocumentListener;\nimport java.awt.*;\nimport java.io.File;\n\n/**\n * @author Baptiste Mesta\n */\npublic class PowerModeConfigurableUI implements ConfigurableUi<PowerMode> {\n\n\n    private JPanel mainPanel;\n    private JCheckBox powerModeEnabled;\n    private JCheckBox shakeEnabled;\n    private JSlider sparkCount;\n    private JSlider sparkLife;\n    private JSlider shakeRange;\n    private JSlider heatup;\n    private JSlider heatupTime;\n    private JLabel sparkCountValue;\n    private JLabel sparkLifeValue;\n    private JLabel shakeRangeValue;\n    private JLabel heatupValue;\n    private JLabel heatupTimeValue;\n    private JSlider maxFlameSize;\n    private JLabel maxFlameSizeValue;\n    private JSlider flameLife;\n    private JLabel flameLifeValue;\n    private JSlider keyStrokesPerMinute;\n    private JLabel keyStrokesPerMinuteValue;\n    private JCheckBox FLAMESCheckBox;\n    private JCheckBox PARTICLESCheckBox;\n    private JSlider sparkSize;\n    private JLabel sparkSizeValue;\n    private JLabel velocityFactorValue;\n    private JLabel gravityFactorValue;\n    private JSlider velocityFactor;\n    private JSlider gravityFactor;\n    private JLabel frameRateValue;\n    private JSlider frameRate;\n    private JSlider sparkColorRedTo;\n    private JSlider sparkColorRedFrom;\n    private JSlider sparkColorGreenFrom;\n    private JSlider sparkColorGreenTo;\n    private JSlider sparkColorBlueFrom;\n    private JSlider sparkColorBlueTo;\n    private JLabel sparkColorRedFromValue;\n    private JLabel sparkColorRedToValue;\n    private JLabel sparkColorGreenFromValue;\n    private JLabel sparkColorGreenToValue;\n    private JLabel sparkColorBlueFromValue;\n    private JLabel sparkColorBlueToValue;\n    private JLabel sparkColorAlphaValue;\n    private JSlider sparkColorAlpha;\n    private JPanel colorView;\n    private JCheckBox visualizeEveryCaretMovementCheckBox;\n    private JCheckBox PLAYMUSICCheckBox;\n    private JTextField soundsFolder;\n    private JCheckBox BAMCheckBox;\n    private JLabel bamLifeValue;\n    private JSlider bamLife;\n    private JLabel heatupThresholdValue;\n    private JSlider heatupThreshold;\n    private JCheckBox PowerIndicatorCheckBox;\n    private JTextField flameImagesFolder;\n    private JTextField bamImagesFolder;\n    private JCheckBox customFlameImages;\n    private JCheckBox customBamImages;\n    private JCheckBox HOTKEYHEATUPCheckBox;\n    private JCheckBox animateBAMImagesCheckBox;\n    private JLabel minVolumeValue;\n    private JSlider minVolume;\n    private JLabel maxVolumeValue;\n    private JSlider maxVolume;\n\n\n    public PowerModeConfigurableUI(PowerMode powerMode) {\n        $$$setupUI$$$();\n        ((MultiGradientPanel) colorView).setColorEdges(PowerMode.obtainColorEdges(powerMode));\n        new ColorViewController((MultiGradientPanel) colorView, powerMode);\n        powerModeEnabled.setSelected(powerMode.isEnabled());\n        shakeEnabled.setSelected(powerMode.isShakeEnabled());\n        shakeEnabled.addChangeListener(e -> powerMode.setShakeEnabled(shakeEnabled.isSelected()));\n        FLAMESCheckBox.setSelected(powerMode.isFlamesEnabled());\n        FLAMESCheckBox.addChangeListener(e -> powerMode.setFlamesEnabled(FLAMESCheckBox.isSelected()));\n        PARTICLESCheckBox.setSelected(powerMode.isSparksEnabled());\n        PARTICLESCheckBox.addChangeListener(e -> powerMode.setSparksEnabled(PARTICLESCheckBox.isSelected()));\n        BAMCheckBox.setSelected(powerMode.isBamEnabled());\n        BAMCheckBox.addChangeListener(e -> powerMode.setIsBamEnabled(BAMCheckBox.isSelected()));\n        visualizeEveryCaretMovementCheckBox.setSelected(powerMode.getIsCaretAction());\n        visualizeEveryCaretMovementCheckBox.addChangeListener(e -> powerMode.setIsCaretAction(visualizeEveryCaretMovementCheckBox.isSelected()));\n        PLAYMUSICCheckBox.setEnabled(powerMode.mediaPlayerExists().isSuccess());\n        PLAYMUSICCheckBox.setSelected(powerMode.isSoundsPlaying() && powerMode.mediaPlayerExists().isSuccess());\n        PLAYMUSICCheckBox.addChangeListener(e -> powerMode.setIsSoundsPlaying(PLAYMUSICCheckBox.isSelected()));\n        HOTKEYHEATUPCheckBox.setSelected(powerMode.isHotkeyHeatup());\n        HOTKEYHEATUPCheckBox.addChangeListener(e -> powerMode.setHotkeyHeatup(HOTKEYHEATUPCheckBox.isSelected()));\n        PowerIndicatorCheckBox.setSelected(powerMode.getIsPowerIndicatorEnabled());\n        PowerIndicatorCheckBox.addChangeListener(e -> powerMode.setIsPowerIndicatorEnabled(PowerIndicatorCheckBox.isSelected()));\n        animateBAMImagesCheckBox.setSelected(!powerMode.getIsSingleBamImagePerEvent());\n        animateBAMImagesCheckBox.addChangeListener(e -> powerMode.setIsSingleBamImagePerEvent(!animateBAMImagesCheckBox.isSelected()));\n\n        soundsFolder.setText(powerMode.getSoundsFolder());\n\n        soundsFolder.getDocument().addDocumentListener(new DocumentListener() {\n            @Override\n            public void insertUpdate(DocumentEvent e) {\n                powerMode.setSoundsFolder(soundsFolder.getText());\n            }\n\n            @Override\n            public void removeUpdate(DocumentEvent e) {\n                powerMode.setSoundsFolder(soundsFolder.getText());\n            }\n\n            @Override\n            public void changedUpdate(DocumentEvent e) {\n                powerMode.setSoundsFolder(soundsFolder.getText());\n            }\n        });\n        initValues(powerMode.getSparkCount(), sparkCount, sparkCountValue, slider -> powerMode.setSparkCount(slider.getValue()));\n        initValues(powerMode.getSparkSize(), sparkSize, sparkSizeValue, slider -> powerMode.setSparkSize(slider.getValue()));\n        initValues(powerMode.getSparkLife(), sparkLife, sparkLifeValue, slider -> powerMode.setSparkLife(slider.getValue()));\n        initValues(Double.valueOf((powerMode.getSparkVelocityFactor() * 100.0)).intValue(), velocityFactor, velocityFactorValue, slider -> powerMode.setSparkVelocityFactor(slider.getValue() / 100.0));\n        initValues(Double.valueOf(powerMode.getGravityFactor() * 100.0).intValue(), gravityFactor, gravityFactorValue, slider -> powerMode.setGravityFactor(slider.getValue() / 100.0));\n        initValues(powerMode.getShakeRange(), shakeRange, shakeRangeValue, slider -> powerMode.setShakeRange(slider.getValue()));\n        initValues(powerMode.getMinVolume(), minVolume, minVolumeValue, slider -> powerMode.setMinVolume(slider.getValue()));\n        initValues(powerMode.getMaxVolume(), maxVolume, maxVolumeValue, slider -> powerMode.setMaxVolume(slider.getValue()));\n        bindSlieders(minVolume, maxVolume);\n        initValues(powerMode.getHeatup(), heatup, heatupValue, slider -> powerMode.setHeatup(slider.getValue()));\n        initValues(powerMode.getHeatupTime(), heatupTime, heatupTimeValue, slider -> powerMode.setHeatupTime(slider.getValue()));\n        initValues(powerMode.getHeatupThreshold(), heatupThreshold, heatupThresholdValue, slider -> powerMode.setHeatupThreshold(slider.getValue()));\n        initValues(powerMode.getFlameLife(), flameLife, flameLifeValue, slider -> powerMode.setFlameLife(slider.getValue()));\n        initValues((int) powerMode.getBamLife(), bamLife, bamLifeValue, slider -> powerMode.setBamLife(slider.getValue()));\n        initValues(powerMode.getmaxFlameSize(), maxFlameSize, maxFlameSizeValue, slider -> powerMode.setmaxFlameSize(slider.getValue()));\n        initValues(powerMode.getKeyStrokesPerMinute(), keyStrokesPerMinute, keyStrokesPerMinuteValue, slider -> powerMode.setKeyStrokesPerMinute(slider.getValue()));\n        initValues(powerMode.getFrameRateHertz(), frameRate, frameRateValue, slider -> powerMode.setFrameRateHertz(slider.getValue()));\n\n        initValuesColor(powerMode.getRedFrom(), sparkColorRedFrom, sparkColorRedFromValue, powerMode, slider -> powerMode.setRedFrom(slider.getValue()));\n        initValuesColor(powerMode.getRedTo(), sparkColorRedTo, sparkColorRedToValue, powerMode, slider -> powerMode.setRedTo(slider.getValue()));\n        bindSlieders(sparkColorRedFrom, sparkColorRedTo);\n\n        initValuesColor(powerMode.getGreenFrom(), sparkColorGreenFrom, sparkColorGreenFromValue, powerMode, slider -> powerMode.setGreenFrom(slider.getValue()));\n        initValuesColor(powerMode.getGreenTo(), sparkColorGreenTo, sparkColorGreenToValue, powerMode, slider -> powerMode.setGreenTo(slider.getValue()));\n        bindSlieders(sparkColorGreenFrom, sparkColorGreenTo);\n\n        initValuesColor(powerMode.getBlueFrom(), sparkColorBlueFrom, sparkColorBlueFromValue, powerMode, slider -> powerMode.setBlueFrom(slider.getValue()));\n        initValuesColor(powerMode.getBlueTo(), sparkColorBlueTo, sparkColorBlueToValue, powerMode, slider -> powerMode.setBlueTo(slider.getValue()));\n        bindSlieders(sparkColorBlueFrom, sparkColorBlueTo);\n\n        initValuesColor(powerMode.getColorAlpha(), sparkColorAlpha, sparkColorAlphaValue, powerMode, slider -> powerMode.setColorAlpha(slider.getValue()));\n\n        customFlameImages.setSelected(powerMode.isCustomFlameImages());\n        customFlameImages.addChangeListener(e -> powerMode.setCustomFlameImages(customFlameImages.isSelected()));\n        {\n            flameImagesFolder.setText(powerMode.getCustomFlameImageFolder());\n\n            flameImagesFolder.getDocument().addDocumentListener(new DocumentListener() {\n                @Override\n                public void insertUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                @Override\n                public void removeUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                @Override\n                public void changedUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                private void setFolder(PowerMode powerMode) {\n                    if (validateImagePath(powerMode,\n                            PowerModeConfigurableUI.this.flameImagesFolder,\n                            PowerModeConfigurableUI.this.customFlameImages)) {\n                        powerMode.setCustomFlameImageFolder(flameImagesFolder.getText());\n                    }\n                }\n            });\n        }\n\n        customBamImages.setSelected(powerMode.isCustomBamImages());\n        customBamImages.addChangeListener(e -> powerMode.setCustomBamImages(customBamImages.isSelected()));\n\n        {\n            bamImagesFolder.setText(powerMode.getCustomBamImageFolder());\n\n            bamImagesFolder.getDocument().addDocumentListener(new DocumentListener() {\n                @Override\n                public void insertUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                @Override\n                public void removeUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                @Override\n                public void changedUpdate(DocumentEvent e) {\n                    setFolder(powerMode);\n                }\n\n                private void setFolder(PowerMode powerMode) {\n                    if (validateImagePath(powerMode,\n                            PowerModeConfigurableUI.this.bamImagesFolder,\n                            PowerModeConfigurableUI.this.customBamImages)) {\n                        powerMode.setCustomBamImageFolder(bamImagesFolder.getText());\n                    }\n                }\n            });\n        }\n    }\n\n    private boolean validateImagePath(PowerMode powerMode, JTextField flameImagesFolder, JCheckBox customFlameImages) {\n        String folder = flameImagesFolder.getText();\n        File file = new File(folder).getAbsoluteFile();\n        if (!file.exists() || file.getAbsolutePath().toLowerCase().contains(\"temp\") || file.getAbsolutePath().toLowerCase().contains(\"tmp\")) {\n            customFlameImages.setSelected(false);\n            JOptionPane.showMessageDialog(mainPanel,\n                    \"invalid folder! Folder '\" + file.getAbsolutePath() + \"' does not exist or is a temp file (contains 'Temp' or 'tmp')\", \"invalid folder\",\n                    JOptionPane.ERROR_MESSAGE);\n            return false;\n        } else {\n            return true;\n        }\n    }\n\n    private void bindSlieders(JSlider from, JSlider to) {\n        from.addChangeListener(new ChangeListener() {\n            @Override\n            public void stateChanged(ChangeEvent e) {\n                if (from.getValue() > to.getValue()) {\n                    to.setValue(from.getValue());\n                }\n            }\n        });\n        to.addChangeListener(new ChangeListener() {\n            @Override\n            public void stateChanged(ChangeEvent e) {\n                if (to.getValue() < from.getValue()) {\n                    from.setValue(to.getValue());\n                }\n            }\n        });\n    }\n\n    private void initValuesColor(int initValue, JSlider slider, JLabel sliderValueLabel, PowerMode powerMode, ValueColorSettable valueSettable) {\n        initValues(initValue, slider, sliderValueLabel, slider1 -> {\n            valueSettable.setValue(slider1);\n            ((MultiGradientPanel) colorView).setColorEdges(PowerMode.obtainColorEdges(powerMode));\n        });\n\n    }\n\n    private void initValues(int initValue, JSlider slider, JLabel sliderValueLabel, ValueSettable valueSettable) {\n        slider.setValue(initValue);\n        sliderValueLabel.setText(String.valueOf(initValue));\n        slider.addChangeListener(new MyChangeListener(slider, sliderValueLabel) {\n            @Override\n            public void setValue(JSlider slider) {\n                valueSettable.setValue(slider);\n            }\n        });\n    }\n\n    @Override\n    public void reset(PowerMode powerMode) {\n        powerModeEnabled.setSelected(powerMode.isEnabled());\n    }\n\n    @Override\n    public boolean isModified(PowerMode powerMode) {\n        return powerModeEnabled.isSelected() != powerMode.isEnabled();\n    }\n\n    @Override\n    public void apply(PowerMode powerMode) throws ConfigurationException {\n        powerMode.setEnabled(powerModeEnabled.isSelected());\n    }\n\n\n    @Override\n    public JComponent getComponent() {\n        return mainPanel;\n    }\n\n    private void createUIComponents() {\n        colorView = new MultiGradientPanel(200, PowerMode.obtainColorEdges(PowerMode.getInstance()));\n\n\n    }\n\n    /**\n     * Method generated by IntelliJ IDEA GUI Designer\n     * >>> IMPORTANT!! <<<\n     * DO NOT edit this method OR call it in your code!\n     *\n     * @noinspection ALL\n     */\n    private void $$$setupUI$$$() {\n        createUIComponents();\n        mainPanel = new JPanel();\n        mainPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));\n        final JTabbedPane tabbedPane1 = new JTabbedPane();\n        tabbedPane1.setTabLayoutPolicy(0);\n        mainPanel.add(tabbedPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false));\n        final JPanel panel1 = new JPanel();\n        panel1.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));\n        tabbedPane1.addTab(\"GENERAL OPTIONS\", panel1);\n        final JScrollPane scrollPane1 = new JScrollPane();\n        scrollPane1.setEnabled(true);\n        panel1.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));\n        final JPanel panel2 = new JPanel();\n        panel2.setLayout(new GridLayoutManager(19, 3, new Insets(0, 0, 0, 0), -1, -1));\n        scrollPane1.setViewportView(panel2);\n        final JLabel label1 = new JLabel();\n        label1.setText(\"framerate\");\n        label1.setToolTipText(\"particle & flame updates per second\");\n        panel2.add(label1, new GridConstraints(18, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        frameRateValue = new JLabel();\n        frameRateValue.setText(\"Label\");\n        panel2.add(frameRateValue, new GridConstraints(18, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        frameRate = new JSlider();\n        frameRate.setMaximum(120);\n        frameRate.setMinimum(5);\n        frameRate.setValue(30);\n        panel2.add(frameRate, new GridConstraints(18, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        powerModeEnabled = new JCheckBox();\n        powerModeEnabled.setText(\"ENTER POWER MODE!\");\n        panel2.add(powerModeEnabled, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        PARTICLESCheckBox = new JCheckBox();\n        PARTICLESCheckBox.setText(\"SPARKS!\");\n        panel2.add(PARTICLESCheckBox, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        shakeEnabled = new JCheckBox();\n        shakeEnabled.setText(\"SHAKE!\");\n        panel2.add(shakeEnabled, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        FLAMESCheckBox = new JCheckBox();\n        FLAMESCheckBox.setText(\"FLAMES!\");\n        panel2.add(FLAMESCheckBox, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        visualizeEveryCaretMovementCheckBox = new JCheckBox();\n        visualizeEveryCaretMovementCheckBox.setText(\"VISUALIZE EVERY CARET MOVEMENT!\");\n        visualizeEveryCaretMovementCheckBox.setToolTipText(\"When disabled: only typing of letters will cause effects.\\nWhen enabled: every caret movement will cause effects.\");\n        panel2.add(visualizeEveryCaretMovementCheckBox, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        PLAYMUSICCheckBox = new JCheckBox();\n        PLAYMUSICCheckBox.setText(\"PLAY MUSIC\");\n        PLAYMUSICCheckBox.setToolTipText(\"next song: shift ctrl alt M\");\n        panel2.add(PLAYMUSICCheckBox, new GridConstraints(8, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        soundsFolder = new JTextField();\n        panel2.add(soundsFolder, new GridConstraints(8, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));\n        BAMCheckBox = new JCheckBox();\n        BAMCheckBox.setText(\"BAM!\");\n        BAMCheckBox.setToolTipText(\"visualize document changes with BAM!\");\n        panel2.add(BAMCheckBox, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label2 = new JLabel();\n        label2.setText(\"BAM! life [ms]\");\n        panel2.add(label2, new GridConstraints(15, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        bamLifeValue = new JLabel();\n        bamLifeValue.setText(\"Label\");\n        panel2.add(bamLifeValue, new GridConstraints(15, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        bamLife = new JSlider();\n        bamLife.setMaximum(10000);\n        panel2.add(bamLife, new GridConstraints(15, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        PowerIndicatorCheckBox = new JCheckBox();\n        PowerIndicatorCheckBox.setText(\"POWER INDICATOR!\");\n        PowerIndicatorCheckBox.setToolTipText(\"Displays an imprecise visualization of the current heatup value.\");\n        panel2.add(PowerIndicatorCheckBox, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label3 = new JLabel();\n        label3.setText(\"shake range [px]\");\n        label3.setToolTipText(\"how many pixels should the shaking move?\");\n        panel2.add(label3, new GridConstraints(9, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        final JLabel label4 = new JLabel();\n        label4.setText(\"min volume %\");\n        label4.setToolTipText(\"how many pixels should the shaking move?\");\n        panel2.add(label4, new GridConstraints(10, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        final JLabel label5 = new JLabel();\n        label5.setText(\"max volume %\");\n        label5.setToolTipText(\"how many pixels should the shaking move?\");\n        panel2.add(label5, new GridConstraints(11, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        shakeRangeValue = new JLabel();\n        shakeRangeValue.setText(\"Label\");\n        panel2.add(shakeRangeValue, new GridConstraints(9, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        minVolumeValue = new JLabel();\n        minVolumeValue.setText(\"Label\");\n        panel2.add(minVolumeValue, new GridConstraints(10, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        maxVolumeValue = new JLabel();\n        maxVolumeValue.setText(\"Label\");\n        panel2.add(maxVolumeValue, new GridConstraints(11, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        shakeRange = new JSlider();\n        panel2.add(shakeRange, new GridConstraints(9, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        minVolume = new JSlider();\n        panel2.add(minVolume, new GridConstraints(10, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        maxVolume = new JSlider();\n        panel2.add(maxVolume, new GridConstraints(11, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label6 = new JLabel();\n        label6.setText(\"max flame size [px]\");\n        label6.setToolTipText(\"maximum flame size in pixels\");\n        panel2.add(label6, new GridConstraints(12, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        maxFlameSizeValue = new JLabel();\n        maxFlameSizeValue.setText(\"Label\");\n        panel2.add(maxFlameSizeValue, new GridConstraints(12, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        maxFlameSize = new JSlider();\n        maxFlameSize.setMaximum(500);\n        panel2.add(maxFlameSize, new GridConstraints(12, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label7 = new JLabel();\n        label7.setText(\"flame life [ms]\");\n        label7.setToolTipText(\"time to live for a flame in milliseconds\");\n        panel2.add(label7, new GridConstraints(13, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        flameLifeValue = new JLabel();\n        flameLifeValue.setText(\"Label\");\n        panel2.add(flameLifeValue, new GridConstraints(13, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        flameLife = new JSlider();\n        flameLife.setMaximum(10000);\n        panel2.add(flameLife, new GridConstraints(13, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label8 = new JLabel();\n        label8.setText(\"hint: 'heatup base level' should be <100%\");\n        panel2.add(label8, new GridConstraints(7, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        customFlameImages = new JCheckBox();\n        customFlameImages.setText(\"custom flame images\");\n        customFlameImages.setToolTipText(\"provide a folder with the images of a flame animation\");\n        panel2.add(customFlameImages, new GridConstraints(14, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        flameImagesFolder = new JTextField();\n        panel2.add(flameImagesFolder, new GridConstraints(14, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));\n        final JLabel label9 = new JLabel();\n        label9.setText(\"image folder:\");\n        panel2.add(label9, new GridConstraints(14, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        customBamImages = new JCheckBox();\n        customBamImages.setText(\"custom BAM! images\");\n        customBamImages.setToolTipText(\"choose your own BAM! images\");\n        panel2.add(customBamImages, new GridConstraints(16, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        animateBAMImagesCheckBox = new JCheckBox();\n        animateBAMImagesCheckBox.setText(\"animate BAM! images\");\n        animateBAMImagesCheckBox.setToolTipText(\"will cycle through all BAM! images in the given folder and create an animation (like a GIF).\");\n        panel2.add(animateBAMImagesCheckBox, new GridConstraints(17, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        bamImagesFolder = new JTextField();\n        panel2.add(bamImagesFolder, new GridConstraints(16, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));\n        final JLabel label10 = new JLabel();\n        label10.setText(\"image folder:\");\n        panel2.add(label10, new GridConstraints(16, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        HOTKEYHEATUPCheckBox = new JCheckBox();\n        HOTKEYHEATUPCheckBox.setText(\"HOTKEY HEATUP\");\n        HOTKEYHEATUPCheckBox.setToolTipText(\"Disable if having problems with hotkey visualization\");\n        panel2.add(HOTKEYHEATUPCheckBox, new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label11 = new JLabel();\n        label11.setText(\"!!! might interfere with autocompletion and other plugins/editors!\");\n        panel2.add(label11, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label12 = new JLabel();\n        label12.setText(\"music folder:\");\n        panel2.add(label12, new GridConstraints(8, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final Spacer spacer1 = new Spacer();\n        panel1.add(spacer1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));\n        final JScrollPane scrollPane2 = new JScrollPane();\n        tabbedPane1.addTab(\"HEATUP\", scrollPane2);\n        final JPanel panel3 = new JPanel();\n        panel3.setLayout(new GridLayoutManager(6, 3, new Insets(0, 0, 0, 0), -1, -1));\n        scrollPane2.setViewportView(panel3);\n        panel3.setBorder(BorderFactory.createTitledBorder(null, \"Heatup\", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));\n        final JLabel label13 = new JLabel();\n        label13.setText(\"heatup base level [%]\");\n        label13.setToolTipText(\"the lower the level the fewer happens at the start of typing.\");\n        panel3.add(label13, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        heatupValue = new JLabel();\n        heatupValue.setText(\"Label\");\n        panel3.add(heatupValue, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        heatup = new JSlider();\n        panel3.add(heatup, new GridConstraints(3, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label14 = new JLabel();\n        label14.setText(\"heatup time [ms]\");\n        label14.setToolTipText(\"time range in milliseconds. The count of keystrokes in this period is used to calculate heatup.\");\n        panel3.add(label14, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        heatupTimeValue = new JLabel();\n        heatupTimeValue.setText(\"Label\");\n        panel3.add(heatupTimeValue, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        heatupTime = new JSlider();\n        heatupTime.setMaximum(60000);\n        panel3.add(heatupTime, new GridConstraints(4, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label15 = new JLabel();\n        label15.setText(\"heatup threshold [%]\");\n        label15.setToolTipText(\"how much heatup in % has to be reached until something happens\");\n        panel3.add(label15, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        heatupThresholdValue = new JLabel();\n        heatupThresholdValue.setText(\"Label\");\n        panel3.add(heatupThresholdValue, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        heatupThreshold = new JSlider();\n        heatupThreshold.setMaximum(100);\n        heatupThreshold.setMinimum(0);\n        heatupThreshold.setValue(30);\n        panel3.add(heatupThreshold, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label16 = new JLabel();\n        label16.setText(\"keystrokes per minute\");\n        label16.setToolTipText(\"used to calculate heatup\");\n        panel3.add(label16, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        keyStrokesPerMinuteValue = new JLabel();\n        keyStrokesPerMinuteValue.setText(\"Label\");\n        panel3.add(keyStrokesPerMinuteValue, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        keyStrokesPerMinute = new JSlider();\n        keyStrokesPerMinute.setMaximum(3000);\n        keyStrokesPerMinute.setValue(100);\n        panel3.add(keyStrokesPerMinute, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JTextArea textArea1 = new JTextArea();\n        textArea1.setEditable(false);\n        textArea1.setEnabled(true);\n        textArea1.setText(\"Heatup is the dynamic power factor in % which defines how much\\n sparkling and fire is happening. \\nIts calculated by 'keystrokes per minute' constant, \\nthe 'heatup time'- window and how much typing and hotkeying is done within that time window.\\n'heatup base level' is the minimum heatup that is always active. \\n'heatup threshold' is the minimum heatup required such that things start happening.\\n\\n\");\n        panel3.add(textArea1, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(150, 50), null, 0, false));\n        final Spacer spacer2 = new Spacer();\n        panel3.add(spacer2, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));\n        final JScrollPane scrollPane3 = new JScrollPane();\n        tabbedPane1.addTab(\"SPARKS\", scrollPane3);\n        final JPanel panel4 = new JPanel();\n        panel4.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));\n        scrollPane3.setViewportView(panel4);\n        final JPanel panel5 = new JPanel();\n        panel5.setLayout(new GridLayoutManager(16, 3, new Insets(0, 0, 0, 0), -1, -1));\n        panel4.add(panel5, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 245), null, 0, false));\n        panel5.setBorder(BorderFactory.createTitledBorder(null, \"Sparks\", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));\n        sparkColorRedFromValue = new JLabel();\n        sparkColorRedFromValue.setText(\"Label\");\n        panel5.add(sparkColorRedFromValue, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorRedFrom = new JSlider();\n        sparkColorRedFrom.setMaximum(255);\n        panel5.add(sparkColorRedFrom, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        panel5.add(colorView, new GridConstraints(0, 0, 11, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(200, 200), new Dimension(200, 200), new Dimension(200, 200), 0, false));\n        final JLabel label17 = new JLabel();\n        label17.setText(\"spark color red range\");\n        label17.setToolTipText(\"how many sparks should appear?\");\n        panel5.add(label17, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(136, 14), null, 0, false));\n        sparkColorRedToValue = new JLabel();\n        sparkColorRedToValue.setText(\"Label\");\n        panel5.add(sparkColorRedToValue, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorRedTo = new JSlider();\n        sparkColorRedTo.setMaximum(255);\n        panel5.add(sparkColorRedTo, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label18 = new JLabel();\n        label18.setText(\"spark color green range\");\n        label18.setToolTipText(\"how many sparks should appear?\");\n        panel5.add(label18, new GridConstraints(3, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorGreenFromValue = new JLabel();\n        sparkColorGreenFromValue.setText(\"Label\");\n        panel5.add(sparkColorGreenFromValue, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorGreenFrom = new JSlider();\n        sparkColorGreenFrom.setMaximum(255);\n        panel5.add(sparkColorGreenFrom, new GridConstraints(4, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorGreenToValue = new JLabel();\n        sparkColorGreenToValue.setText(\"Label\");\n        panel5.add(sparkColorGreenToValue, new GridConstraints(5, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorGreenTo = new JSlider();\n        sparkColorGreenTo.setMaximum(255);\n        panel5.add(sparkColorGreenTo, new GridConstraints(5, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label19 = new JLabel();\n        label19.setText(\"spark color blue range\");\n        label19.setToolTipText(\"how many sparks should appear?\");\n        panel5.add(label19, new GridConstraints(6, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorBlueFromValue = new JLabel();\n        sparkColorBlueFromValue.setText(\"Label\");\n        panel5.add(sparkColorBlueFromValue, new GridConstraints(7, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorBlueFrom = new JSlider();\n        sparkColorBlueFrom.setMaximum(255);\n        panel5.add(sparkColorBlueFrom, new GridConstraints(7, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorBlueToValue = new JLabel();\n        sparkColorBlueToValue.setText(\"Label\");\n        panel5.add(sparkColorBlueToValue, new GridConstraints(8, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorBlueTo = new JSlider();\n        sparkColorBlueTo.setMaximum(255);\n        panel5.add(sparkColorBlueTo, new GridConstraints(8, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label20 = new JLabel();\n        label20.setText(\"alpha\");\n        panel5.add(label20, new GridConstraints(9, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorAlphaValue = new JLabel();\n        sparkColorAlphaValue.setText(\"Label\");\n        panel5.add(sparkColorAlphaValue, new GridConstraints(10, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkColorAlpha = new JSlider();\n        sparkColorAlpha.setMaximum(255);\n        panel5.add(sparkColorAlpha, new GridConstraints(10, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label21 = new JLabel();\n        label21.setText(\"spark count\");\n        label21.setToolTipText(\"how many sparks should appear?\");\n        panel5.add(label21, new GridConstraints(11, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        sparkCountValue = new JLabel();\n        sparkCountValue.setText(\"Label\");\n        panel5.add(sparkCountValue, new GridConstraints(11, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkCount = new JSlider();\n        sparkCount.setMaximum(100);\n        panel5.add(sparkCount, new GridConstraints(11, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label22 = new JLabel();\n        label22.setText(\"spark life [ms]\");\n        label22.setToolTipText(\"how many milliseconds should a spark live?\");\n        panel5.add(label22, new GridConstraints(12, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        sparkLifeValue = new JLabel();\n        sparkLifeValue.setText(\"Label\");\n        panel5.add(sparkLifeValue, new GridConstraints(12, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkLife = new JSlider();\n        sparkLife.setMaximum(10000);\n        panel5.add(sparkLife, new GridConstraints(12, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label23 = new JLabel();\n        label23.setText(\"spark size [px]\");\n        label23.setToolTipText(\"spark size in pixels\");\n        panel5.add(label23, new GridConstraints(13, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        sparkSizeValue = new JLabel();\n        sparkSizeValue.setText(\"Label\");\n        panel5.add(sparkSizeValue, new GridConstraints(13, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        sparkSize = new JSlider();\n        sparkSize.setMaximum(10);\n        panel5.add(sparkSize, new GridConstraints(13, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label24 = new JLabel();\n        label24.setText(\"spark velocity factor %\");\n        label24.setToolTipText(\"100% is default spark velocity\");\n        panel5.add(label24, new GridConstraints(14, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        velocityFactorValue = new JLabel();\n        velocityFactorValue.setText(\"Label\");\n        panel5.add(velocityFactorValue, new GridConstraints(14, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        velocityFactor = new JSlider();\n        velocityFactor.setMaximum(10000);\n        velocityFactor.setMinimum(-10000);\n        velocityFactor.setValue(100);\n        panel5.add(velocityFactor, new GridConstraints(14, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final JLabel label25 = new JLabel();\n        label25.setText(\"spark gravity factor %\");\n        label25.setToolTipText(\"100% is default spark gravity\");\n        panel5.add(label25, new GridConstraints(15, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(176, 15), null, 0, false));\n        gravityFactorValue = new JLabel();\n        gravityFactorValue.setText(\"Label\");\n        panel5.add(gravityFactorValue, new GridConstraints(15, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        gravityFactor = new JSlider();\n        gravityFactor.setMaximum(10000);\n        gravityFactor.setMinimum(-10000);\n        gravityFactor.setValue(100);\n        panel5.add(gravityFactor, new GridConstraints(15, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));\n        final Spacer spacer3 = new Spacer();\n        panel4.add(spacer3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));\n    }\n\n    /**\n     * @noinspection ALL\n     */\n    public JComponent $$$getRootComponent$$$() {\n        return mainPanel;\n    }\n\n    private interface ValueColorSettable {\n        void setValue(JSlider slider);\n    }\n\n    private abstract class MyChangeListener implements ChangeListener, ValueSettable {\n        private final JSlider slider;\n        private final JLabel jLabel;\n\n        public MyChangeListener(JSlider slider, JLabel jLabel) {\n            this.slider = slider;\n            this.jLabel = jLabel;\n        }\n\n        @Override\n        public void stateChanged(ChangeEvent e) {\n            setValue(slider);\n            jLabel.setText(String.valueOf(slider.getValue()));\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/ValueSettable.java",
    "content": "package de.ax.powermode.power.ui;\n\nimport javax.swing.*;\n\n/**\n * Created by nyxos on 11.03.16.\n */\npublic interface ValueSettable {\n    void setValue(JSlider slider);\n}\n"
  },
  {
    "path": "src/main/java/javazoom/jl/player/HackyJavaSoundAudioDevice.java",
    "content": "/*\n * 11/26/04\t\tBuffer size modified to support JRE 1.5 optimizations.\n *              (CPU usage < 1% under P4/2Ghz, RAM < 12MB).\n *              jlayer@javazoom.net\n * 11/19/04\t\t1.0 moved to LGPL.\n * 06/04/01\t\tToo fast playback fixed. mdm@techie.com\n * 29/01/00\t\tInitial version. mdm@techie.com\n *-----------------------------------------------------------------------\n *   This program is free software; you can redistribute it and/or modify\n *   it under the terms of the GNU Library General Public License as published\n *   by the Free Software Foundation; either version 2 of the License, or\n *   (at your option) any later version.\n *\n *   This program is distributed in the hope that it will be useful,\n *   but WITHOUT ANY WARRANTY; without even the implied warranty of\n *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *   GNU Library General Public License for more details.\n *\n *   You should have received a copy of the GNU Library General Public\n *   License along with this program; if not, write to the Free Software\n *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n *----------------------------------------------------------------------\n */\n\npackage javazoom.jl.player;\n\nimport javax.sound.sampled.AudioFormat;\nimport javax.sound.sampled.AudioSystem;\nimport javax.sound.sampled.DataLine;\nimport javax.sound.sampled.Line;\nimport javax.sound.sampled.LineUnavailableException;\nimport javax.sound.sampled.SourceDataLine;\n\nimport javazoom.jl.decoder.Decoder;\nimport javazoom.jl.decoder.JavaLayerException;\n\n/**\n * The <code>JavaSoundAudioDevice</code> implements an audio\n * device by using the JavaSound API.\n *\n * @author Mat McGowan\n * @since 0.0.8\n */\npublic class HackyJavaSoundAudioDevice extends AudioDeviceBase {\n    public SourceDataLine source = null;\n\n    public AudioFormat fmt = null;\n\n    public byte[] byteBuf = new byte[4096];\n\n    protected void setAudioFormat(AudioFormat fmt0) {\n        fmt = fmt0;\n    }\n\n    protected AudioFormat getAudioFormat() {\n        if (fmt == null) {\n            Decoder decoder = getDecoder();\n            fmt = new AudioFormat(decoder.getOutputFrequency(),\n                    16,\n                    decoder.getOutputChannels(),\n                    true,\n                    false);\n        }\n        return fmt;\n    }\n\n    protected DataLine.Info getSourceLineInfo() {\n        AudioFormat fmt = getAudioFormat();\n        //DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000);\n        DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);\n        return info;\n    }\n\n    public void open(AudioFormat fmt) throws JavaLayerException {\n        if (!isOpen()) {\n            setAudioFormat(fmt);\n            openImpl();\n            setOpen(true);\n        }\n    }\n\n    protected void openImpl()\n            throws JavaLayerException {\n    }\n\n\n    // createSource fix.\n    protected void createSource() throws JavaLayerException {\n        Throwable t = null;\n        try {\n            Line line = AudioSystem.getLine(getSourceLineInfo());\n            if (line instanceof SourceDataLine) {\n                source = (SourceDataLine) line;\n                //source.open(fmt, millisecondsToBytes(fmt, 2000));\n                source.open(fmt);\n                /*\n                if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))\n                {\n\t\t\t\t\tFloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);\n                    c.setValue(c.getMaximum());\n                }*/\n                source.start();\n\n            }\n        } catch (RuntimeException ex) {\n            t = ex;\n        } catch (LinkageError ex) {\n            t = ex;\n        } catch (LineUnavailableException ex) {\n            t = ex;\n        }\n        if (source == null) throw new JavaLayerException(\"cannot obtain source audio line\", t);\n    }\n\n    public int millisecondsToBytes(AudioFormat fmt, int time) {\n        return (int) (time * (fmt.getSampleRate() * fmt.getChannels() * fmt.getSampleSizeInBits()) / 8000.0);\n    }\n\n    protected void closeImpl() {\n        if (source != null) {\n            source.close();\n        }\n    }\n\n    protected void writeImpl(short[] samples, int offs, int len)\n            throws JavaLayerException {\n        if (source == null)\n            createSource();\n\n        byte[] b = toByteArray(samples, offs, len);\n        source.write(b, 0, len * 2);\n    }\n\n    protected byte[] getByteArray(int length) {\n        if (byteBuf.length < length) {\n            byteBuf = new byte[length + 1024];\n        }\n        return byteBuf;\n    }\n\n    protected byte[] toByteArray(short[] samples, int offs, int len) {\n        byte[] b = getByteArray(len * 2);\n        int idx = 0;\n        short s;\n        while (len-- > 0) {\n            s = samples[offs++];\n            b[idx++] = (byte) s;\n            b[idx++] = (byte) (s >>> 8);\n        }\n        return b;\n    }\n\n    protected void flushImpl() {\n        if (source != null) {\n            source.drain();\n        }\n    }\n\n    public int getPosition() {\n        int pos = 0;\n        if (source != null) {\n            pos = (int) (source.getMicrosecondPosition() / 1000);\n        }\n        return pos;\n    }\n\n    /**\n     * Runs a short test by playing a short silent sound.\n     */\n    public void test()\n            throws JavaLayerException {\n        try {\n            open(new AudioFormat(22050, 16, 1, true, false));\n            short[] data = new short[22050 / 10];\n            write(data, 0, data.length);\n            flush();\n            close();\n        } catch (RuntimeException ex) {\n            throw new JavaLayerException(\"Device test failed: \" + ex);\n        }\n\n    }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/ImageUtil.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.util.PathUtil\nimport de.ax.powermode.cache.Cache\nimport de.ax.powermode.power.element.PowerFlame\n\nimport java.awt.image.BufferedImage\nimport java.io.{BufferedOutputStream, File, FileOutputStream, InputStream}\nimport java.net.{URI, URL}\nimport javax.imageio.{IIOException, ImageIO}\nimport scala.util.{Failure, Success, Try}\n\nobject ImageUtil {\n  def imagesForPath(folder: Option[File]): scala.List[BufferedImage] = {\n    val orElse = folder.getOrElse(new File(\"UNDEFINED\"))\n    //logger.debug(s\"imagesForPath $folder\")\n    ImageUtil.listCache\n      .getOrUpdate(orElse) {\n        Some(folder.map(ImageUtil.images).toList.flatten.map(f => f()))\n      }\n      .toList\n      .flatten\n  }\n\n  val imageCache =\n    new Cache[URI, BufferedImage, Long](fname => new File(fname).lastModified(),\n                                        fname => !new File(fname).exists())\n\n  var lastUpdate = System.currentTimeMillis()\n\n  val listCache = new Cache[File, List[BufferedImage], File](\n    f => f,\n    f =>\n      if (System.currentTimeMillis() - 5000 > lastUpdate) {\n        lastUpdate = System.currentTimeMillis()\n        true\n      } else false)\n\n  def images(imagesPath: File): List[() => BufferedImage] = {\n    val imageUrls = getImageUrls(imagesPath)\n    getImagesCached(imageUrls).map(img => { () =>\n      ImageUtil.deepCopy(img)\n    })\n  }\n\n  import java.awt.image.BufferedImage\n\n  def deepCopy(bi: BufferedImage): BufferedImage = {\n    val cm = bi.getColorModel\n    val isAlphaPremultiplied = cm.isAlphaPremultiplied\n    val raster = bi.copyData(null)\n    new BufferedImage(cm, raster, isAlphaPremultiplied, null)\n  }\n\n  def getUrl(uri: URI): Try[URL] = Try {\n    uri.toURL\n  }\n\n  private def getImagesCached(imageUrls: List[URI]) = {\n    imageUrls.flatMap(uri =>\n      imageCache.getOrUpdate(uri) {\n        val maybeImg = Try {\n          Option(ImageIO.read(uri.toURL))\n        }\n\n        maybeImg match {\n          case Success(Some(img)) =>\n            val bufferedImage = new BufferedImage(img.getWidth,\n                                                  img.getHeight,\n                                                  BufferedImage.TYPE_INT_ARGB)\n            val graphics = bufferedImage.getGraphics\n            graphics.drawImage(img, 0, 0, null)\n            Some(bufferedImage)\n          case Failure(e) =>\n            e match {\n              case io: IIOException =>\n                PowerMode.logger\n                  .info(\n                    s\"could not load image file! Please try to store your PowerMode \" +\n                      s\"Images/Animations in a different folder and restart the application! File not found: '$uri'!\",\n                    e\n                  )\n              case ex =>\n                PowerMode.logger\n                  .info(\n                    s\"could not load image file! Please try to store your PowerMode \" +\n                      s\"Images/Animations in a different folder and restart the application! File not found: '$uri'!\",\n                    ex\n                  )\n            }\n            None\n          case Success(None) =>\n            PowerMode.logger\n              .info(s\"could not load image from url '${uri.toURL}'\")\n            None\n        }\n    })\n  }\n\n  private def getImageUrls(imagesPath: File): List[URI] = {\n    try {\n      //logger.debug(s\"FILE: $imagesPath\")\n      val urls = if (imagesPath.exists()) {\n        getFileImages(imagesPath)\n      } else if (debugFolderExists(imagesPath)) {\n        getImageUrlsFromDebugDir(imagesPath)\n      } else {\n        getImageUrlsFromResources(imagesPath)\n      }\n      //logger.debug(s\"URLS: $urls\")\n      urls\n    } catch {\n      case e: Throwable =>\n        PowerMode.logger.debug(\n          s\"info getting image urls from '${imagesPath}': ${e.getMessage}\",\n          e)\n        throw e\n    }\n  }\n\n  private def getFileImages(imagesPath: File): List[URI] = {\n    //logger.debug(s\"LOADING FROM normal path: $imagesPath\")\n\n    val files = if (imagesPath.isFile) {\n      List(imagesPath)\n    } else {\n      Option(imagesPath.getAbsoluteFile.listFiles())\n        .map(_.toList)\n        .toList\n        .flatten\n        .filter(_.isFile)\n    }\n    files.map(_.getAbsoluteFile.toURI)\n  }\n\n  private def debugFolderExists(imagesPath: File): Boolean = {\n    val file = new File(PathUtil.getJarPathForClass(classOf[PowerFlame]),\n                        imagesPath.getPath)\n    file.exists()\n  }\n\n  private def getImageUrlsFromDebugDir(imagesPath: File): List[URI] = {\n    val file = new File(PathUtil.getJarPathForClass(classOf[PowerFlame]),\n                        imagesPath.getPath)\n    //logger.debug(s\"LOADING FROM exploded sandbox: $file\")\n    Option(file.listFiles())\n      .map(_.toList)\n      .toList\n      .flatten\n      .filter(_.isFile)\n      .map(_.toURI)\n  }\n\n  def writeBytes(data: LazyList[Byte], file: File) = {\n    val target = new BufferedOutputStream(new FileOutputStream(file))\n    try data.foreach(target.write(_))\n    finally target.close()\n  }\n\n  lazy val fireUrls = (1 to 25)\n    .map(i => if (i > 9) s\"$i\" else s\"0$i\")\n    .map { i =>\n      mkTmpImg(\n        classOf[PowerFlame].getResourceAsStream(\n          s\"/fire/animated/256/fire1_ $i.png\"))\n    }\n    .toList\n\n  lazy val bamUrls =\n    Option(classOf[PowerFlame].getResourceAsStream(s\"/bam/bam.png\"))\n      .map(mkTmpImg)\n      .toList\n\n  private def getImageUrlsFromResources(imagesFolder: File): List[URI] = {\n    val loader = this.getClass().getClassLoader()\n    //logger.debug(s\"LOADING FROM JAR: $imagesFolder\")\n    val uRLs: List[URL] = if (imagesFolder.getPath.contains(\"fire\")) {\n      fireUrls\n    } else if (imagesFolder.getPath.contains(\"bam\")) {\n      bamUrls\n    } else {\n      None.toList\n    }\n    uRLs.map(_.toURI)\n  }\n\n  private def mkTmpImg(stream: InputStream): URL = {\n    import java.io.File\n    val tempFile =\n      File.createTempFile(s\"${System.currentTimeMillis()}_pmtempfile_\", \".png\")\n    tempFile.deleteOnExit()\n    writeBytes(\n      LazyList.continually(stream.read).takeWhile(_ != -1).map(_.toByte),\n      tempFile)\n    tempFile.toURI.toURL\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/MyCaretListener.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.editor.Caret\nimport com.intellij.openapi.editor.event.{CaretEvent, CaretListener}\n\nimport java.util.concurrent.atomic.AtomicInteger\nimport java.util.function.IntUnaryOperator\nimport scala.util.Try\n\n/**\n  * Created by nyxos on 04.01.17.\n  */\nclass MyCaretListener extends CaretListener with Power {\n  var modified = true\n\n  val caretCount = new AtomicInteger(1)\n  override def caretPositionChanged(caretEvent: CaretEvent): Unit = {\n    if (!modified && powerMode.caretAction) {\n      initializeAnimationByCaretEvent(caretEvent.getCaret)\n    }\n    modified = false\n  }\n\n  override def caretRemoved(caretEvent: CaretEvent): Unit = {\n    modified = true\n    caretCount.getAndUpdate((i: Int) => {\n      if (i > 2) {\n        i - 1\n      } else {\n        1\n      }\n    })\n  }\n\n  override def caretAdded(caretEvent: CaretEvent): Unit = {\n    modified = true\n    caretCount.getAndIncrement()\n  }\n\n  private def initializeAnimationByCaretEvent(caret: Caret): Unit = {\n    val isActualEditor = Try {\n      Util.isActualEditor(caret.getEditor)\n    }.getOrElse(false)\n    if (isActualEditor) {\n      Util\n        .getCaretPosition(caret)\n        .toOption\n        .foreach(p =>\n          powerMode.maybeElementOfPowerContainerManager.foreach(\n            _.initializeAnimation(caret.getEditor, p)))\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/MyTypedActionHandler.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.DataContext\nimport com.intellij.openapi.editor.Editor\nimport com.intellij.openapi.editor.actionSystem.TypedActionHandler\n\nimport java.awt.Point\nimport scala.jdk.CollectionConverters._\n\n/**\n  * Created by nyxos on 04.01.17.\n  */\nclass MyTypedActionHandler(typedActionHandler: TypedActionHandler)\n    extends TypedActionHandler\n    with Power {\n\n  def execute(editor: Editor, c: Char, dataContext: DataContext): Unit = {\n    if (powerMode.isEnabled) {\n      powerMode.increaseHeatup(dataContext = Option(dataContext))\n      if (!powerMode.caretAction) {\n        initializeAnimationByTypedAction(editor)\n      }\n    }\n    try {\n      typedActionHandler.execute(editor, c, dataContext)\n    } catch {\n      case x: IllegalStateException =>\n        logger.debug(x.getMessage, x)\n      case x: IndexOutOfBoundsException =>\n        logger.debug(x.getMessage, x)\n    }\n  }\n\n  def getEditorCaretPositions(editor: Editor): Seq[Point] = {\n    editor.getCaretModel.getAllCarets.asScala.toList\n      .map({ c =>\n        Util.getCaretPosition(editor, c)\n      })\n      .filter(_.isSuccess)\n      .map(_.get)\n  }\n\n  def initializeAnimationByTypedAction(editor: Editor): Unit = {\n\n    val isActualEditor = Util.isActualEditor(editor)\n    if (isActualEditor) {\n      val positions = getEditorCaretPositions(editor)\n      positions.foreach(pos => {\n        powerMode.maybeElementOfPowerContainerManager.foreach(\n          _.initializeAnimation(editor, pos))\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/NextSongAction.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}\n\n/**\n  * Created by nyxos on 27.12.16.\n  */\nclass NextSongAction extends AnAction with Power {\n  override def actionPerformed(anActionEvent: AnActionEvent): Unit = {\n    powerMode.maybeElementOfPowerContainerManager.foreach(cm => {\n      cm.sound.foreach(_.next())\n    })\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/Power.scala",
    "content": "package de.ax.powermode\n\n/**\n  * Created by nyxos on 04.01.17.\n  */\ntrait Power {\n  def powerMode: PowerMode = {\n    PowerMode.getInstance\n  }\n\n  def logger = PowerMode.logger\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerMode.scala",
    "content": "/*\n * Copyright 2015 Baptiste Mesta\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 */\npackage de.ax.powermode\n\nimport com.intellij.openapi.Disposable\nimport com.intellij.openapi.actionSystem.DataContext\nimport com.intellij.openapi.application.ApplicationManager\nimport com.intellij.openapi.components.{\n  ApplicationComponent,\n  PersistentStateComponent,\n  Service,\n  State,\n  Storage\n}\nimport com.intellij.openapi.editor.EditorFactory\nimport com.intellij.openapi.editor.actionSystem.{\n  EditorActionManager,\n  TypedAction\n}\nimport com.intellij.util.xmlb.XmlSerializerUtil\nimport de.ax.powermode.PowerMode.logger\nimport de.ax.powermode.power.color.ColorEdges\nimport de.ax.powermode.power.management.ElementOfPowerContainerManager\nimport org.apache.commons.math3.stat.regression.SimpleRegression\nimport com.intellij.openapi.diagnostic.Logger\nimport de.ax.powermode.power.hotkeys.HotkeyHeatupListener\nimport org.jetbrains.annotations.Nullable\nimport squants.Dimensionless\nimport squants.DimensionlessConversions.{DimensionlessConversions, each}\nimport squants.time.Time._\nimport squants.time.Frequency._\nimport squants.time.TimeConversions._\nimport squants.time.FrequencyConversions._\nimport squants.MetricSystem._\nimport squants.time.{Frequency, Time, TimeUnit}\n\nimport scala.language.postfixOps\nimport java.awt.event.InputEvent\nimport java.io.File\nimport javax.swing.KeyStroke\nimport scala.collection.immutable.Seq\nimport scala.util.Try\n\n/**\n  * @author Baptiste Mesta\n  */\nobject PowerMode {\n\n  val logger: Logger = Logger.getInstance(classOf[PowerMode])\n  private var instance: PowerMode = null\n  @Nullable def getInstance: PowerMode = synchronized {\n    if (instance != null) {\n      instance\n    } else {\n      logger.debug(\"No instance!\")\n      try {\n        instance =\n          ApplicationManager.getApplication.getService(classOf[PowerMode])\n        instance.initComponent()\n        instance\n      } catch {\n        case e: Throwable =>\n          logger.debug(\"info getting component: \" + e.getMessage(), e)\n          null\n      }\n    }\n  }\n\n  def obtainColorEdges(pm: PowerMode): ColorEdges = {\n    import pm._\n    val edges = new ColorEdges()\n    edges.setAlpha(getColorAlpha)\n    edges.setRedFrom(getRedFrom)\n    edges.setRedTo(getRedTo)\n    edges.setGreenFrom(getGreenFrom)\n    edges.setGreenTo(getGreenTo)\n    edges.setBlueFrom(getBlueFrom)\n    edges.setBlueTo(getBlueTo)\n    edges\n  }\n}\n\n//@Service(Array(Service.Level.APP))\n@State(name = \"PowerModeII\",\n       storages = Array(new Storage(file = \"$APP_CONFIG$/power.mode.ii.xml\")))\nfinal class PowerMode\n    extends PersistentStateComponent[PowerMode]\n    with Disposable {\n\n  override def dispose(): Unit = {\n    maybeElementOfPowerContainerManager.foreach(_.dispose)\n  }\n\n  type Timestamp = Time\n  type CaretCount = Int\n  type HeatupKey = (Option[KeyStroke], Timestamp, CaretCount)\n  val mediaPlayerExists: Try[Class[_]] = Try {\n    Class.forName(\"javax.sound.sampled.SourceDataLine\")\n  }\n  var isSingleBamImagePerEvent: Boolean = false\n  var hotkeyHeatup: Boolean = true\n  var bamLife: Time = 1000 milliseconds\n  var soundsFolder = Option.empty[File]\n  var minVolume: Dimensionless = 10.percent\n  var maxVolume: Dimensionless = 100.percent\n\n  def getMinVolume: Int = minVolume.toPercent.toInt\n\n  def setMinVolume(value: Int): Unit = {\n    minVolume = value.percent\n    logger.debug(s\"Setting min volume ${minVolume}\")\n    maxVolume = Seq(minVolume, maxVolume).max\n  }\n\n  def getMaxVolume: Int = maxVolume.toPercent.toInt\n\n  def setMaxVolume(value: Int): Unit = {\n    maxVolume = value.percent\n    logger.debug(s\"Setting max volume ${maxVolume}\")\n    minVolume = Seq(minVolume, maxVolume).min\n  }\n\n  var gravityFactor: Double = 21.21\n  var sparkVelocityFactor: Double = 4.36\n  var sparkSize = 3\n  var sparksEnabled = true\n  var frameRate: Frequency = 30 hertz\n  var maxFlameSize: Int = 100\n  var maxFlameLife: Time = 2000 milliseconds\n  var heatupTimeMillis: Time = 10000 milliseconds\n  var lastKeys = List.empty[HeatupKey]\n  var keyStrokesPerMinute: Frequency = 300 / 1.minutes\n  var heatupFactor = 1.0\n  var sparkLife = 3000\n  var sparkCount = 10\n  var shakeRange: Int = 4\n  var flamesEnabled: Boolean = true\n  var maybeElementOfPowerContainerManager\n    : Option[ElementOfPowerContainerManager] =\n    Option.empty\n  var isBamEnabled: Boolean = true\n  var isSoundsPlaying: Boolean = false\n  var powerIndicatorEnabled: Boolean = true\n  var caretAction: Boolean = false\n  var hotkeyWeight: Dimensionless = keyStrokesPerMinute * (3 seconds)\n  var redFrom: Int = 0\n  var redTo: Int = 255\n  var greenFrom: Int = 0\n  var greenTo: Int = 255\n  var blueFrom: Int = 0\n  var blueTo: Int = 255\n  var colorAlpha: Int = 164\n  var heatupThreshold: Double = 0.0\n  var _isCustomFlameImages: Boolean = false\n  var _isCustomBamImages: Boolean = false\n  var customFlameImageFolder = Option.empty[File]\n  var customBamImageFolder = Option.empty[File]\n  private var enabled: Boolean = true\n  private var shakeEnabled: Boolean = false\n\n  def isHotkeyHeatup: Boolean = hotkeyHeatup\n\n  def setHotkeyHeatup(h: Boolean): Unit = {\n    hotkeyHeatup = h\n  }\n\n  def flameImageFolder: Option[File] = {\n    if (!_isCustomFlameImages) Some(new File(\"fire/animated/256\"))\n    else customFlameImageFolder\n  }\n\n  def bamImageFolder: Option[File] = {\n    if (!_isCustomBamImages) Some(new File(\"bam\")) else customBamImageFolder\n  }\n\n  def getFrameRateHertz(): Int = frameRate.toHertz.toInt\n\n  def setFrameRateHertz(f: Int): Unit = {\n    frameRate = f hertz\n  }\n\n  def increaseHeatup(\n      dataContext: Option[DataContext] = Option.empty[DataContext],\n      keyStroke: Option[KeyStroke] = Option.empty[KeyStroke]): Unit = {\n\n    val currentTime = System.currentTimeMillis().milliseconds\n    lastKeys = (keyStroke, currentTime, myCaretListener.caretCount.get()) :: filterLastKeys(\n      currentTime)\n    dataContext.foreach(dc =>\n      maybeElementOfPowerContainerManager.foreach(_.showIndicator(dc)))\n\n  }\n\n  var previousValues = List.empty[Double]\n\n  def reduceHeatup: Unit = {\n    val ct = System.currentTimeMillis().milliseconds\n    lastKeys = filterLastKeys(ct)\n    adjustValueFactor\n  }\n\n  private def adjustValueFactor: Unit = {\n    if (previousValues.size > frameRate.toHertz) {\n      previousValues = previousValues.dropRight(1)\n    }\n    val unlimited = rawValueFactorUnlimited\n    val wouldValues = unlimited :: previousValues\n    val slope = if (wouldValues.size > 1) {\n      val s = new SimpleRegression()\n      wouldValues.zipWithIndex.foreach {\n        case (e, i) =>\n          s.addData(i, e)\n      }\n      s.getSlope\n    } else {\n      0\n    }\n    val maxSlope = 0.001\n    val maxSlopeValue = 0.0005\n    if (slope > maxSlope) {\n      rvf *= (1.0 + maxSlopeValue)\n    } else if (slope < -maxSlope) {\n      rvf *= (1.0 - maxSlopeValue)\n    } else {\n      rvf = unlimited\n    }\n    previousValues ::= rvf\n  }\n\n  private def filterLastKeys(currentTime: Time): List[HeatupKey] = {\n    lastKeys.filter(_._2 >= currentTime - heatupTimeMillis)\n  }\n  var rvf: Double = 0.0\n  def rawValueFactor: Double = { rvf }\n  def rawValueFactorUnlimited: Double = {\n    val base = heatupFactor +\n      ((1 - heatupFactor) * rawTimeFactorFromKeyStrokes)\n    (base - heatupThreshold) / (1 - heatupThreshold)\n  }\n\n  def rawTimeFactorFromKeyStrokes: Double = {\n    val tf = Try {\n      if (heatupTimeMillis < 1.seconds) {\n        1 ea\n      } else {\n        val MaxKeystrokesOverHeatupTime\n          : Dimensionless = heatupTimeMillis * keyStrokesPerMinute\n        val vals: Seq[Dimensionless] = lastKeys.map {\n          case (Some(ks), _, caretCount) =>\n            val size = Seq(InputEvent.CTRL_DOWN_MASK,\n                           InputEvent.ALT_DOWN_MASK,\n                           InputEvent.SHIFT_DOWN_MASK)\n              .count(m => (ks.getModifiers & m) > 0)\n            (size * hotkeyWeight * caretCount)\n          case (_, _, caretCount) => 1.ea * caretCount\n        }\n\n        val keystrokesOverHeatupTime: Dimensionless = vals.foldLeft(0.ea)(_ + _)\n        val res = (keystrokesOverHeatupTime / MaxKeystrokesOverHeatupTime).ea\n        res\n      }\n    }.getOrElse(0 ea)\n    tf.toEach\n  }\n\n  def valueFactor: Dimensionless = {\n    math.min(math.max(rawValueFactor, 0), 1) * 100.percent\n  }\n\n  def timeFactor: Dimensionless = {\n    math.min(math.max(rawTimeFactorFromKeyStrokes, 0), 1) * 100.percent\n  }\n  val myCaretListener = new MyCaretListener()\n  // NOTE: this is called in the constructor, at the very end of this file 👇\n  def initComponent(): Unit = {\n    PowerMode.logger.debug(s\"initComponent... ${System.out.hashCode()}\",\n                           new Exception(\"let's trace the origin\"))\n    logger.debug(\"initComponentPrinted...\")\n    val editorFactory = EditorFactory.getInstance\n    maybeElementOfPowerContainerManager = Some(\n      new ElementOfPowerContainerManager)\n    maybeElementOfPowerContainerManager.foreach(\n      editorFactory.addEditorFactoryListener(_, this))\n\n    EditorFactory\n      .getInstance()\n      .getEventMulticaster\n      .addCaretListener(myCaretListener, this)\n    maybeElementOfPowerContainerManager.map(cm => {\n      val typedAction = TypedAction\n        .getInstance()\n      typedAction\n        .setupRawHandler(new MyTypedActionHandler(typedAction.getRawHandler))\n    })\n    val l = new HotkeyHeatupListener\n    PowerMode.logger.debug(\"initComponent done\")\n  }\n\n  override def getState: PowerMode = {\n    this\n  }\n\n  override def loadState(state: PowerMode): Unit = {\n    XmlSerializerUtil.copyBean(state, this)\n  }\n\n  def isEnabled: Boolean = {\n    enabled\n  }\n\n  def setEnabled(enabled: Boolean): Unit = {\n    this.enabled = enabled\n  }\n\n  def isShakeEnabled: Boolean = {\n    shakeEnabled\n  }\n\n  def setShakeEnabled(shakeEnabled: Boolean): Unit = {\n    this.shakeEnabled = shakeEnabled\n  }\n\n  def getSparkCount: Int = sparkCount\n\n  def setSparkCount(sparkCount: Int): Unit = {\n    this.sparkCount = sparkCount\n  }\n\n  def getSparkLife: Int = sparkLife\n\n  def setSparkLife(sparkRange: Int): Unit = {\n    this.sparkLife = sparkRange\n  }\n\n  def getShakeRange: Int = shakeRange\n\n  def setShakeRange(shakeRange: Int): Unit = {\n    this.shakeRange = shakeRange\n  }\n\n  def getHeatup: Int = (heatupFactor * 100).toInt\n\n  def setHeatup(heatup: Int): Unit = {\n    this.heatupFactor = heatup / 100.0\n  }\n\n  def getHeatupTime: Int = heatupTimeMillis.toMilliseconds.toInt\n\n  def setHeatupTime(heatupTime: Int): Unit = {\n    this.heatupTimeMillis = math.max(0, heatupTime) milliseconds\n  }\n\n  def getFlameLife: Int = {\n    maxFlameLife.toMilliseconds.toInt\n  }\n\n  def setFlameLife(flameLife: Int): Unit = {\n    maxFlameLife = flameLife.milliseconds\n  }\n\n  def getmaxFlameSize: Int = {\n    maxFlameSize\n  }\n\n  def setmaxFlameSize(maxFlameSize: Int): Unit = {\n    this.maxFlameSize = maxFlameSize\n  }\n\n  def getKeyStrokesPerMinute: Int = {\n    (keyStrokesPerMinute * 1.minutes).toEach.toInt\n  }\n\n  def setKeyStrokesPerMinute(keyStrokesPerMinute: Int): Unit = {\n    this.keyStrokesPerMinute = keyStrokesPerMinute / 1.minutes\n  }\n\n  def isFlamesEnabled: Boolean = {\n    flamesEnabled\n  }\n\n  def setFlamesEnabled(flamesEnabled: Boolean): Unit = {\n    this.flamesEnabled = flamesEnabled\n  }\n\n  def isSparksEnabled: Boolean = {\n    sparksEnabled\n  }\n\n  def setSparksEnabled(sparksEnabled: Boolean): Unit = {\n    this.sparksEnabled = sparksEnabled\n  }\n\n  def getSparkSize: Int = {\n    sparkSize\n  }\n\n  def setSparkSize(sparkSize: Int): Unit = {\n    this.sparkSize = sparkSize\n  }\n\n  def getGravityFactor(): Double = gravityFactor\n\n  def setGravityFactor(f: Double): Unit = {\n    gravityFactor = f\n  }\n\n  def getSparkVelocityFactor(): Double = sparkVelocityFactor\n\n  def setSparkVelocityFactor(f: Double): Unit = {\n    sparkVelocityFactor = f\n  }\n\n  def getRedFrom: Int = {\n    redFrom\n  }\n\n  def setRedFrom(redFrom: Int): Unit = {\n    if (redFrom <= redTo)\n      this.redFrom = redFrom\n  }\n\n  def getRedTo: Int = {\n    redTo\n  }\n\n  def setRedTo(redTo: Int): Unit = {\n    if (redTo >= redFrom)\n      this.redTo = redTo\n  }\n\n  def getGreenTo: Int = {\n    greenTo\n  }\n\n  def setGreenTo(greenTo: Int): Unit = {\n    if (greenTo >= greenFrom)\n      this.greenTo = greenTo\n  }\n\n  def getGreenFrom: Int = {\n    greenFrom\n  }\n\n  def setGreenFrom(gf: Int): Unit = {\n    if (gf <= greenTo)\n      greenFrom = gf\n  }\n\n  def getBlueTo: Int = {\n    blueTo\n  }\n\n  def setBlueTo(blueTo: Int): Unit = {\n    if (blueTo >= getBlueFrom)\n      this.blueTo = blueTo\n  }\n\n  def getBlueFrom: Int = {\n    blueFrom\n  }\n\n  def setBlueFrom(bf: Int): Unit = {\n    if (bf <= blueTo)\n      blueFrom = bf\n  }\n\n  def getColorAlpha: Int = {\n    colorAlpha\n  }\n\n  def setColorAlpha(alpha: Int): Unit = {\n    colorAlpha = alpha\n  }\n\n  def getSoundsFolder: String =\n    soundsFolder.map(_.getAbsolutePath).getOrElse(\"\")\n\n  def setSoundsFolder(file: String): Unit = {\n    soundsFolder = Option(new File(file))\n  }\n\n  def getIsCaretAction: Boolean = {\n    caretAction\n  }\n\n  def setIsCaretAction(isCaretAction: Boolean): Unit = {\n    this.caretAction = isCaretAction\n  }\n\n  def getIsSoundsPlaying: Boolean = isSoundsPlaying\n\n  def setIsSoundsPlaying(isSoundsPlaying: Boolean): Unit = {\n    this.isSoundsPlaying = isSoundsPlaying\n  }\n\n  def getBamLife: Double = bamLife.toMilliseconds\n\n  def setBamLife(l: Long): Unit = {\n    bamLife = l.milliseconds\n  }\n\n  def getIsBamEnabled: Boolean = isBamEnabled\n\n  def setIsBamEnabled(b: Boolean): Unit = {\n    isBamEnabled = b\n  }\n\n  def getHeatupThreshold: Int = {\n    (heatupThreshold * 100.0).toInt\n  }\n\n  def setHeatupThreshold(t: Int): Unit = {\n    heatupThreshold = t / 100.0\n  }\n\n  def getIsPowerIndicatorEnabled: Boolean = {\n    powerIndicatorEnabled\n  }\n\n  def setIsPowerIndicatorEnabled(enabled: Boolean): Unit = {\n    powerIndicatorEnabled = enabled\n  }\n\n  def isCustomFlameImages: Boolean = _isCustomFlameImages\n\n  def setCustomFlameImages(s: Boolean): Unit = {\n    _isCustomFlameImages = s\n  }\n\n  def isCustomBamImages: Boolean = _isCustomBamImages\n\n  def setCustomBamImages(s: Boolean): Unit = {\n    _isCustomBamImages = s\n  }\n\n  def getCustomFlameImageFolder: String =\n    customFlameImageFolder.map(_.getAbsolutePath).getOrElse(\"\")\n\n  def setCustomFlameImageFolder(file: String): Unit = {\n    customFlameImageFolder = Option(new File(file))\n  }\n\n  def getCustomBamImageFolder: String =\n    customBamImageFolder.map(_.getAbsolutePath).getOrElse(\"\")\n\n  def setCustomBamImageFolder(file: String): Unit = {\n    customBamImageFolder = Option(new File(file))\n  }\n\n  def getIsSingleBamImagePerEvent(): Boolean = {\n    isSingleBamImagePerEvent\n  }\n\n  def setIsSingleBamImagePerEvent(isSingleBamImagePerEvent: Boolean): Unit = {\n    this.isSingleBamImagePerEvent = isSingleBamImagePerEvent\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerModeConfigurable.scala",
    "content": "/*\n * Copyright 2015 Baptiste Mesta\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 */\npackage de.ax.powermode\n\nimport com.intellij.openapi.options.ConfigurableBase\nimport de.ax.powermode.power.ui.PowerModeConfigurableUI\n\n/**\n  * @author Baptiste Mesta\n  */\nclass PowerModeConfigurable()\n    extends ConfigurableBase[PowerModeConfigurableUI, PowerMode](\n      \"power.mode.II\",\n      \"Power Mode II\",\n      \"power.mode.II\") {\n  val settings: PowerMode = PowerMode.getInstance\n\n  protected def getSettings: PowerMode = {\n    if (settings == null) {\n      throw new IllegalStateException(\"power mode is null\")\n    }\n    settings\n  }\n\n  protected def createUi: PowerModeConfigurableUI = {\n    new PowerModeConfigurableUI(settings)\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerModeStartup.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.startup.StartupActivity\n\nimport java.util\nobject PowerModeStartup {\n  def start(): Unit = synchronized {\n    PowerMode.logger.debug(s\"starting instance on out ${System.out.hashCode()}\")\n    val x = PowerMode.getInstance\n    PowerMode.logger.debug(s\"started instance ${x.hashCode()}\")\n  }\n}\nclass PowerModeStartup extends com.intellij.ide.AppLifecycleListener {\n  override def appFrameCreated(commandLineArgs: util.List[String]): Unit = {\n    PowerModeStartup.start()\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/TogglePowerMode.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}\n\n/**\n  * Created by nyxos on 31.03.16.\n  */\nclass TogglePowerMode extends AnAction with Power {\n  def actionPerformed(e: AnActionEvent): Unit = {\n    powerMode.setEnabled(!powerMode.isEnabled)\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/Util.scala",
    "content": "package de.ax.powermode\n\nimport com.intellij.openapi.editor.impl.EditorImpl\nimport com.intellij.openapi.editor.{Caret, Editor, EditorKind, VisualPosition}\n\nimport java.awt.Point\nimport scala.util.Try\n\n/**\n  * Created by nyxos on 30.09.16.\n  */\nobject Util {\n  def alpha(f: Float): Float = {\n    if (f < 0) {\n      0f\n    } else if (f > 1) {\n      1f\n    } else {\n      f\n    }\n  }\n\n  def isActualEditor(editor: Editor): Boolean = {\n    println(\n      s\"editor.getClass: ${editor.getClass} ${editor.toString} ${editor.getEditorKind} ${editor.getDocument.isWritable}\")\n    editor match {\n      case e if e.isViewer =>\n        false\n      case e if e.isOneLineMode =>\n        false\n      case impl: EditorImpl =>\n        try {\n          Set(EditorKind.MAIN_EDITOR, EditorKind.DIFF)\n            .contains(impl.getEditorKind)\n        } catch {\n          case _: Throwable => false\n        }\n      case _ =>\n        false\n    }\n  }\n\n  def editorOk(editor: Editor, maxSize: Int): Boolean = {\n    !(editor match {\n      case impl: EditorImpl =>\n        try {\n          impl.getPreferredSize.height < maxSize || impl.getPreferredSize.width < maxSize\n        } catch {\n          case _: Throwable => true\n        }\n      case _ =>\n        false\n    })\n  }\n\n  def interceptError[T](f: => T): T = {\n    try {\n      f\n    } catch {\n      case e: Throwable =>\n        throw e\n    }\n  }\n\n  def getPoint(position: VisualPosition, editor: Editor): Point = {\n    val p: Point = editor.visualPositionToXY(position)\n    val location = editor.getScrollingModel.getVisibleArea.getLocation\n    p.translate(-location.x, -location.y)\n    p\n  }\n\n  def getCaretPosition(caret: Caret): Try[Point] = Try {\n    getPoint(caret.getVisualPosition, caret.getEditor)\n  }\n\n  def getCaretPosition(editor: Editor, c: Caret): Try[Point] = Try {\n    val p: Point = editor.visualPositionToXY(c.getVisualPosition)\n    val location = editor.getScrollingModel.getVisibleArea.getLocation\n    p.translate(-location.x, -location.y)\n    p\n  }\n\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/cache/Cache.scala",
    "content": "package de.ax.powermode.cache\n\nimport scala.collection.mutable;\n\nclass Cache[K, V, I](compareValue: K => I, shoudUpdate: K => Boolean) {\n\n  val cache: mutable.HashMap[K, (V, I)] = mutable.HashMap.empty[K, (V, I)]\n\n  def getOrUpdate(k: K)(orUpdate: => Option[V]): Option[V] = {\n    var kInfo = compareValue(k)\n    val maybeV1 = if (shoudUpdate(k)) {\n      None\n    } else {\n      cache\n        .get(k)\n        .collect { case (v, i) => if (kInfo == i) Some(v) else None }\n        .flatten\n    }\n    maybeV1 match {\n      case Some(v) =>\n        Some(v)\n      case None =>\n        val nvo = orUpdate\n        nvo.map(nv => cache.put(k, (nv, kInfo)))\n        nvo\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/package.scala",
    "content": "/**\n  * Created by nyxos on 13.03.16.\n  */\npackage object powermode {\n\n  type PowerColor = (Float, Float, Float, Float)\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/ElementOfPower.scala",
    "content": "package de.ax.powermode.power\n\nimport de.ax.powermode.Power\n\nimport java.awt.Graphics\n\n/**\n  * Created by nyxos on 10.03.16.\n  */\ntrait ElementOfPower extends Power {\n\n  def update(delta: Float): Boolean\n\n  def render(g: Graphics, dxx: Int, dyy: Int): Unit\n\n  def life: Long\n\n  def initLife: Long\n\n  def lifeFactor: Float = {\n    1 - ((life - System.currentTimeMillis()) / initLife.toFloat)\n  }\n\n  def alive: Boolean = {\n    life > System\n      .currentTimeMillis() && powerMode.isEnabled //&& width >= 0 && width <= _width\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/color/ColorEdges.scala",
    "content": "package de.ax.powermode.power.color\n\nimport java.awt.Color\n\nclass ColorEdges(var leftTop: MyPaint = MyPaint(0, 0, 0, 255),\n                 var rightTop: MyPaint = MyPaint(255, 0, 0, 255),\n                 var leftBottom: MyPaint = MyPaint(0, 255, 0, 255),\n                 var rightBottom: MyPaint = MyPaint(255, 255, 0, 255)) {\n\n  implicit def mp2Color(mp: MyPaint): Color = mp.color\n\n  def getLeftTop: Color = {\n    return leftTop\n  }\n\n  def getRightTop: Color = {\n    return rightTop\n  }\n\n  def getLeftBottom: Color = {\n    return leftBottom\n  }\n\n  def getRightBottom: Color = {\n    return rightBottom\n  }\n\n  def updateColors(c1: Int): Unit = {\n    leftTop = updateMyPaint(c1, leftTop)\n    rightTop = updateMyPaint(c1, rightTop)\n    leftBottom = updateMyPaint(c1, leftBottom)\n    rightBottom = updateMyPaint(c1, rightBottom)\n  }\n\n  private def updateMyPaint(c: Int, MyPaint: MyPaint): MyPaint = {\n    return MyPaint.withBlue(c)\n  }\n\n  def setLeftTop(leftTop: MyPaint): Unit = {\n    this.leftTop = leftTop\n  }\n\n  def setRightTop(rightTop: MyPaint): Unit = {\n    this.rightTop = rightTop\n  }\n\n  def setLeftBottom(leftBottom: MyPaint): Unit = {\n    this.leftBottom = leftBottom\n  }\n\n  def setRightBottom(rightBottom: MyPaint): Unit = {\n    this.rightBottom = rightBottom\n  }\n\n  def setRedFrom(redFrom: Int): Unit = {\n    this.leftTop = leftTop.withRed(redFrom)\n    this.leftBottom = leftBottom.withRed(redFrom)\n  }\n\n  def setRedTo(redTo: Int): Unit = {\n    this.rightTop = rightTop.withRed(redTo)\n    this.rightBottom = rightBottom.withRed(redTo)\n  }\n\n  def setGreenFrom(redFrom: Int): Unit = {\n    this.leftTop = leftTop.withGreen(redFrom)\n    this.rightTop = rightTop.withGreen(redFrom)\n  }\n\n  def setGreenTo(redTo: Int): Unit = {\n    this.leftBottom = leftBottom.withGreen(redTo)\n    this.rightBottom = rightBottom.withGreen(redTo)\n  }\n\n  def setBlueFrom(redFrom: Int): Unit = {\n    this.leftTop = leftTop.withBlue(redFrom)\n    this.leftBottom = leftBottom.withBlue(redFrom)\n  }\n\n  def setBlueTo(redTo: Int): Unit = {\n    this.rightTop = rightTop.withBlue(redTo)\n    this.rightBottom = rightBottom.withBlue(redTo)\n  }\n\n  def setAlpha(alpha: Int): Unit = {\n    this.leftTop = leftTop.withAlpha(alpha)\n    this.leftBottom = leftBottom.withAlpha(alpha)\n    this.rightTop = rightTop.withAlpha(alpha)\n    this.rightBottom = rightBottom.withAlpha(alpha)\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/color/MyPaint.scala",
    "content": "package de.ax.powermode.power.color\n\nimport java.awt.Color\n\n/**\n  * Created by nyxos on 05.07.16.\n  */\ncase class MyPaint(r: Int, g: Int, b: Int, a: Int = 255) {\n  def withRed(rr: Int) = copy(r = rr)\n\n  def withGreen(gg: Int) = copy(g = gg)\n\n  def withBlue(bb: Int) = copy(b = bb)\n\n  def withAlpha(aa: Int) = copy(a = aa)\n\n  lazy val color = new Color(r, g, b, a)\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerBam.scala",
    "content": "package de.ax.powermode.power.element\n\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.{ImageUtil, Util}\n\nimport java.awt.image.BufferedImage\nimport java.awt.{AlphaComposite, Graphics, Graphics2D}\nimport scala.language.postfixOps\n\n/**\n  * Created by nyxos on 28.12.16.\n  */\ncase class PowerBam(_x: Float,\n                    _y: Float,\n                    var _width: Float,\n                    var _height: Float,\n                    initLife: Long)\n    extends ElementOfPower {\n  logger.debug(s\"x ${_x}, y ${_y}, w ${_width}, h ${_height}\")\n\n  val life = System.currentTimeMillis() + initLife\n  var x: Double = _x\n  var y: Double = _y\n  var width: Double = 0\n  var height: Double = 0\n\n  var i = 0\n\n  var currentImage: Option[BufferedImage] =\n    if (powerMode.isSingleBamImagePerEvent) {\n      val bis = ImageUtil.imagesForPath(powerMode.bamImageFolder)\n      val img = bis((math.random() * (bis.size - 1)) % bis.size toInt)\n      val ih = img.getWidth / img.getHeight.toDouble\n      logger.debug(s\"img ${img.getWidth} / ${img.getHeight}\")\n      logger.debug(s\"old ${_width} ${_height}\")\n      if (ih > 1) {\n        _height = (_height / ih).toFloat\n        _width = _width\n      } else {\n        _height = _height\n        _width = (_width * ih).toFloat\n      }\n      logger.debug(s\"new ${_width} ${_height}\")\n      Option(img)\n    } else {\n      None\n    }\n\n  override def update(delta: Float): Boolean = {\n    if (alive) {\n      if (!powerMode.isSingleBamImagePerEvent) {\n        val bis = ImageUtil.imagesForPath(powerMode.bamImageFolder)\n        if (bis.nonEmpty) {\n          currentImage = Option(bis(i % bis.size))\n        }\n      }\n      i += 1\n      x = _x + (0.5 * _width) - (0.5 * _width * lifeFactor)\n      y = _y + (0.5 * _height) - (0.5 * _height * lifeFactor)\n      width = _width * lifeFactor\n      height = _height * lifeFactor\n    }\n    !alive\n  }\n\n  override def render(g: Graphics, dxx: Int, dyy: Int): Unit = {\n    currentImage.foreach { currentImage =>\n      if (alive) {\n        val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]\n        g2d.setComposite(\n          AlphaComposite.getInstance(AlphaComposite.SRC_OVER,\n                                     Util.alpha(0.9f * (1 - lifeFactor))))\n        g2d.drawImage(currentImage,\n                      x + dxx toInt,\n                      y + dyy toInt,\n                      width toInt,\n                      height toInt,\n                      null)\n        g2d.dispose()\n      }\n    }\n\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerFlame.scala",
    "content": "package de.ax.powermode.power.element\n\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.{ImageUtil, Util}\n\nimport java.awt.image.BufferedImage\nimport java.awt.{AlphaComposite, Graphics, Graphics2D}\n\ncase class PowerFlame(_x: Int,\n                      _y: Int,\n                      _width: Int,\n                      _height: Int,\n                      initLife: Long,\n                      up: Boolean)\n    extends ElementOfPower {\n  val life = System.currentTimeMillis() + initLife\n  var x = _x\n  var y = _y\n  var width = 0\n  var height = 0\n\n  var i = 0\n  var currentImage: BufferedImage = null\n\n  override def update(delta: Float): Boolean = {\n    if (alive) {\n      val flameImages1 = ImageUtil.imagesForPath(powerMode.flameImageFolder)\n      if (flameImages1.nonEmpty) {\n        currentImage = flameImages1(i % flameImages1.size)\n      }\n      i += 1\n      x = _x - (0.5 * _width * lifeFactor).toInt\n      if (up)\n        y = _y - (1.1 * _height * lifeFactor).toInt\n      else\n        y = _y + (0.25 * _height * lifeFactor).toInt\n      width = (_width * lifeFactor).toInt\n      height = (_height * lifeFactor).toInt\n    }\n    !alive\n  }\n\n  override def render(g: Graphics, dxx: Int, dyy: Int): Unit = {\n    if (alive) {\n\n      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]\n      g2d.setComposite(\n        AlphaComposite.getInstance(AlphaComposite.SRC_OVER,\n                                   Util.alpha(0.9f * (1 - lifeFactor))))\n\n      if (up) {\n        if (currentImage != null)\n          g2d.drawImage(currentImage, x + dxx, y + dyy, width, height, null)\n      } else {\n        // flip horizontally\n        if (currentImage != null)\n          g2d.drawImage(currentImage,\n                        x + dxx,\n                        y + dyy + height,\n                        width,\n                        -height,\n                        null)\n      }\n      g2d.dispose()\n    }\n  }\n\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerIndicator.scala",
    "content": "package de.ax.powermode.power.element\n\nimport com.intellij.openapi.editor.Editor\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.{PowerMode, Util}\nimport squants.DimensionlessConversions.DimensionlessConversions\n\nimport java.awt._\nimport java.awt.image.BufferedImage\nimport scala.annotation.tailrec\nimport scala.collection.mutable\nimport scala.language.postfixOps\nimport scala.ref.WeakReference\n\n/**\n  * Created by nyxos on 25.02.17.\n  */\nobject PowerIndicator {\n  var indicators = mutable.Queue.empty[PowerIndicator]\n\n  def addIndicator(i: PowerIndicator): Unit = {\n    this.synchronized {\n      PowerIndicator.indicators += i\n      PowerIndicator.indicators = PowerIndicator.indicators.filter(i => i.alive)\n    }\n  }\n\n  val grands = Seq(\"perfect\",\n                   \"excellent\",\n                   \"superb\",\n                   \"sublime\",\n                   \"dominating\",\n                   \"marvelous\",\n                   \"splendid\",\n                   \"majestic\",\n                   \"unreal\",\n                   \"fabulous\",\n                   \"great\")\n\n  var lastGrand = Option.empty[String]\n\n  def genGrand: String = {\n    @tailrec\n    def nextGrand(lastGrand: Option[String]): String = {\n      val grand = grands((Math.random() * 100023451).toInt % grands.length) + \"!\"\n      if (lastGrand.contains(grand)) {\n        nextGrand(lastGrand)\n      } else {\n        grand\n      }\n    }\n\n    if (math.random * 100.percent < Seq(\n          1.percent,\n          0.2 * PowerMode.getInstance.valueFactor).max) {\n      val grand = nextGrand(lastGrand)\n      lastGrand = Some(grand)\n      grand\n    } else {\n      \"\"\n    }\n  }\n}\n\ncase class PowerIndicator(_x: Float,\n                          _y: Float,\n                          _width: Float,\n                          _height: Float,\n                          initLife: Long,\n                          editor: WeakReference[Editor])\n    extends ElementOfPower {\n  val identifier = System.currentTimeMillis() + (Math.random() * 1000000)\n  var diffLife = Option.empty[Long]\n  var x: Double = _x\n  var y: Double = _y\n  var width: Double = 0\n  var height: Double = 0\n  PowerIndicator.addIndicator(this)\n  val life2 = System.currentTimeMillis() + initLife\n  val grand = PowerIndicator.genGrand\n\n  override def life = {\n\n    if (isLast) {\n      math.max(life2.toDouble, System.currentTimeMillis() + (initLife * 0.75)) toLong\n    } else {\n      diffLife = Some(\n        diffLife.getOrElse(\n          System.currentTimeMillis() + (initLife * 0.75) toLong))\n      diffLife.get\n    }\n  }\n\n  def isLast: Boolean = {\n    PowerIndicator.indicators != null && PowerIndicator.indicators.lastOption\n      .filter(_ != null)\n      .exists(i => identifier == i.identifier)\n  }\n\n  override def update(delta: Float): Boolean = {\n    if (alive) {\n      x = _x + (0.5 * _width) - (0.5 * _width * (1 - lifeFactor))\n      y = _y + (0.5 * _height) - (0.5 * _height * (1 - lifeFactor))\n      width = _width * (1 - lifeFactor)\n      height = _height * (1 - lifeFactor)\n    }\n    !alive\n  }\n\n  var lastScrollPosition = Option.empty[(Int, Int)]\n\n  override def render(g: Graphics, _dxx: Int, _dyy: Int): Unit = {\n    def limit(v: Int, max: Int): Int = {\n      //      if (v > max) max else if (v < -max) -max else v\n      v\n    }\n\n    if (alive && powerMode.isEnabled && powerMode.powerIndicatorEnabled) {\n      val Some((dxx, dyy)) = lastScrollPosition\n        .map(lp => {\n          val (nx, ny) =\n            (editor.get.get.getScrollingModel.getHorizontalScrollOffset,\n             editor.get.get.getScrollingModel.getVerticalScrollOffset)\n          (lp._1 - nx, lp._2 - ny)\n        })\n        .orElse(Some(0, 0))\n        .map { case (x, y) => (limit(x, 100), limit(y, 100)) }\n      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]\n      g2d.setComposite(\n        AlphaComposite.getInstance(\n          AlphaComposite.SRC_OVER,\n          Util.alpha(1f * (1 - lifeFactor) * (1 - lifeFactor))))\n\n      val bufferedImage =\n        new BufferedImage(600, 600, BufferedImage.TYPE_INT_ARGB)\n      val graphics = bufferedImage.getGraphics\n      drawIndicator(graphics.asInstanceOf[Graphics2D],\n                    bufferedImage.getWidth,\n                    bufferedImage.getHeight)\n      g2d.drawImage(bufferedImage,\n                    math.max(x, 0) - dxx toInt,\n                    math.max(y, 0) - dyy toInt,\n                    width toInt,\n                    height toInt,\n                    null)\n      g2d.dispose()\n      lastScrollPosition = Some(\n        (editor.get.get.getScrollingModel.getHorizontalScrollOffset,\n         editor.get.get.getScrollingModel.getVerticalScrollOffset))\n    }\n  }\n\n  private def drawIndicator(graphics: Graphics2D, width: Int, height: Int) = {\n    graphics.setColor(Color.darkGray)\n    graphics.fillRect(10, 10, width - 10, 200)\n    graphics.setColor(Color.white)\n    graphics.setFont(new Font(\"Dialog\", Font.PLAIN, 100))\n    graphics.drawString((powerMode.rawValueFactor * 100).toInt.toString + \" %\",\n                        10,\n                        100)\n    graphics.setColor(Color.white)\n    graphics.drawString(grand, 10, 200)\n    graphics.setColor(Color.white)\n    var f =\n      math.min(powerMode.rawValueFactor, 20 + (powerMode.rawValueFactor % 1))\n    var max: Double = math.ceil(f)\n    val maxLines = 8\n\n    val maxYSpace = 30 * maxLines / max\n    var barHeight = math.min(50, 0.75 * maxYSpace) toInt\n    var barSpace = math.min(17, 0.25 * maxYSpace) toInt\n\n    while (f > 0) {\n      graphics.setColor(Color.white)\n      graphics.fillRect(10,\n                        height - (((max.toInt + 1) - math\n                          .ceil(f)) * (barSpace + barHeight)) toInt,\n                        width * (if (f >= 1) 1 else f) - 10 toInt,\n                        barHeight)\n      graphics.setColor(Color.black)\n      graphics.setStroke(new BasicStroke(10))\n      graphics.drawRect(9,\n                        height - (((max.toInt + 1) - math\n                          .ceil(f)) * (barSpace + barHeight)) - 1 toInt,\n                        width * (if (f >= 1) 1 else f) - 1 - 10 toInt,\n                        barHeight - 1)\n      f -= 1\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerSpark.scala",
    "content": "/*\n * Copyright 2015 Baptiste Mesta\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 */\npackage de.ax.powermode.power.element\n\nimport de.ax.powermode.Util\nimport de.ax.powermode.power.ElementOfPower\nimport powermode.PowerColor\n\nimport java.awt._\n\n/**\n  * @author Baptiste Mesta\n  */\ncase class PowerSpark(var x: Float,\n                      var y: Float,\n                      dx: Float,\n                      var dy: Float,\n                      size: Float,\n                      val initLife: Long,\n                      color: PowerColor,\n                      gravityFactor: Float)\n    extends ElementOfPower {\n  val life = System.currentTimeMillis() + initLife\n\n  def update(delta: Float): Boolean = {\n    dy += (0.07f * gravityFactor) * delta\n    x += dx * delta\n    y += dy * delta\n    !alive\n  }\n\n  def render(g: Graphics, dxx: Int, dyy: Int): Unit = {\n    if (alive) {\n      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]\n      g2d.setColor(\n        new Color(color._1, color._2, color._3, Util.alpha(color._4)))\n      g2d.fillOval((dxx + x - (size / 2)).toInt,\n                   (dyy + y - (size / 2)).toInt,\n                   size.toInt,\n                   size.toInt)\n      g2d.dispose()\n    }\n  }\n\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/hotkeys/HotkeyHeatupListener.scala",
    "content": "package de.ax.powermode.power.hotkeys\n\nimport com.intellij.ide.DataManager\nimport com.intellij.openapi.actionSystem._\nimport com.intellij.openapi.components.ApplicationComponent\nimport com.intellij.openapi.keymap.KeymapManager\nimport com.intellij.openapi.wm.ToolWindowManager\nimport com.intellij.openapi.wm.ex.ToolWindowManagerListener\nimport com.intellij.util.{SlowOperations, ThrowableRunnable}\nimport de.ax.powermode.Power\nimport java.awt._\nimport java.awt.event._\nimport java.util\nimport javax.swing._\n\nclass HotkeyHeatupListener extends AWTEventListener with Power {\n\n  lazy val allActionKeyStrokes: Set[KeyStroke] =\n    actionsToKeyStrokes.values.flatten.toSet\n\n  lazy val actionsToKeyStrokes = {\n    Map(\n      KeymapManager.getInstance.getActiveKeymap.getActionIds.toList\n        .map(ActionManager.getInstance.getAction)\n        .filter(a => a != null && a.getShortcutSet != null)\n        .map { a =>\n          val keyStrokes = a.getShortcutSet.getShortcuts.toList\n            .filter(_.isKeyboard)\n            .filter(_.isInstanceOf[KeyboardShortcut])\n            .map(_.asInstanceOf[KeyboardShortcut])\n            .flatMap(a => Seq(a.getFirstKeyStroke, a.getSecondKeyStroke))\n          (a, keyStrokes)\n        }: _*)\n  }\n\n  override def eventDispatched(e: AWTEvent): Unit = {\n    SlowOperations.allowSlowOperations(new ThrowableRunnable[Exception] {\n      override def run(): Unit = {\n        if (powerMode.isEnabled && powerMode.isHotkeyHeatup) {\n          e match {\n            case event: KeyEvent => {\n              if ((event.getModifiersEx & (InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) > 0) {\n\n                val eventKeyStroke =\n                  KeyStroke.getKeyStroke(event.getKeyCode, event.getModifiersEx)\n                val isHotkey = allActionKeyStrokes.contains(eventKeyStroke)\n                if (isHotkey) {\n                  powerMode.increaseHeatup(\n                    Option(\n                      DataManager\n                        .getInstance()\n                        .getDataContext(event.getComponent)),\n                    Option(eventKeyStroke))\n                }\n              }\n            }\n            case _ =>\n          }\n        }\n\n      }\n    })\n  }\n  Toolkit.getDefaultToolkit.addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK)\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/management/ElementOfPowerContainer.scala",
    "content": "/*\n * Copyright 2015 Baptiste Mesta\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 */\npackage de.ax.powermode.power.management\n\nimport com.intellij.openapi.diagnostic.Logger\nimport com.intellij.openapi.editor.event._\nimport com.intellij.openapi.editor.{Editor, ScrollingModel}\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.power.element.{\n  PowerBam,\n  PowerFlame,\n  PowerIndicator,\n  PowerSpark\n}\nimport de.ax.powermode.{Power, Util}\nimport powermode.PowerColor\nimport squants.Dimensionless\nimport squants.DimensionlessConversions.{\n  DimensionlessConversions,\n  dimensionlessToDouble,\n  each\n}\nimport squants.time.Time._\nimport squants.time.Frequency._\nimport squants.time.TimeConversions._\nimport squants.time.FrequencyConversions._\nimport squants.MetricSystem._\nimport squants.time.{Frequency, Time, TimeUnit}\n\nimport scala.language.postfixOps\nimport java.awt.event.{ComponentEvent, ComponentListener}\nimport java.awt.{Graphics, Point, Rectangle}\nimport java.util.TimerTask\nimport javax.swing._\nimport scala.jdk.CollectionConverters._\nimport scala.language.postfixOps\nimport scala.ref.WeakReference\n\nobject ElementOfPowerContainer {\n  private val logger = Logger.getInstance(this.getClass)\n}\n\n/**\n  * @author Baptiste Mesta\n  */\nclass ElementOfPowerContainer(editor: WeakReference[Editor])\n    extends JComponent\n    with ComponentListener\n    with Power {\n\n  private val _myParent: Option[WeakReference[JComponent]] =\n    editor.get.map(_.getContentComponent).map(WeakReference.apply)\n  private def myParent: Option[JComponent] = _myParent.flatMap(_.get)\n  myParent.foreach { myParent =>\n    myParent.add(this)\n    this.setBounds(myParent.getBounds)\n    setVisible(true)\n    myParent.addComponentListener(this)\n  }\n\n  val shakeComponents: Seq[JComponent] =\n    Seq(editor.get.map(_.getComponent), editor.get.map(_.getContentComponent)).flatten\n  var elementsOfPower: Seq[(ElementOfPower, (Int, Int))] = Seq.empty\n  var lastShake: Long = System.currentTimeMillis()\n  var shakeData: Option[(Int, Int, Int, Int)] = Option.empty\n\n  var lastUpdate: Long = System.currentTimeMillis()\n\n  var lastPositions: Seq[(Point, Point)] = Seq.empty\n  editor.get.foreach(_.getCaretModel.addCaretListener(new CaretListener {\n\n    def changeCarets: Unit = {\n      lastPositions = {\n        editor.get.toSeq.flatMap(editor =>\n          editor.getCaretModel.getAllCarets.asScala.toSeq.map(caret => {\n            (Util.getPoint(\n               editor.offsetToVisualPosition(caret.getSelectionStart),\n               caret.getEditor),\n             Util.getPoint(editor.offsetToVisualPosition(caret.getSelectionEnd),\n                           caret.getEditor))\n          }))\n      }\n    }\n\n    override def caretPositionChanged(e: CaretEvent): Unit = changeCarets\n\n    override def caretAdded(e: CaretEvent): Unit = changeCarets\n\n    override def caretRemoved(e: CaretEvent): Unit = changeCarets\n  }))\n  private val self: ElementOfPowerContainer = this\n\n  editor.get.foreach(_.getDocument.addDocumentListener(new DocumentListener {\n    val wr: WeakReference[ElementOfPowerContainer] = WeakReference(self)\n    override def documentChanged(documentEvent: DocumentEvent): Unit = {\n\n      wr.get match {\n        case Some(elementOfPowerContainer) =>\n          elementOfPowerContainer.initializeCaretBam(documentEvent)\n        case None => documentEvent.getDocument.removeDocumentListener(this)\n      }\n    }\n  }))\n\n  private def initializeCaretBam(e: DocumentEvent) = {\n    if (powerMode.isBamEnabled) {\n      editor.get.foreach { editor =>\n        val shouldAnimate = {\n          e.getNewFragment.length() > 100 ||\n          e.getOldFragment.length() > 100 ||\n          e.getOldFragment.toString.count('\\n' == _) > 1 ||\n          e.getNewFragment.toString.count('\\n' == _) > 1\n        }\n        if (shouldAnimate) {\n          val width = {\n            val l = (e.getOldFragment.toString + e.getNewFragment.toString)\n              .split(\"\\n\")\n            if (l.nonEmpty) {\n              (l.maxBy(_.length).length / 2.0) * editor.getLineHeight\n            } else {\n              0\n            }\n          }\n          val timer = new java.util.Timer()\n          timer.schedule(new TimerTask {\n            override def run(): Unit = {\n              SwingUtilities.invokeLater(() => {\n                performCaretBam(width)\n              })\n            }\n          }, 300)\n        }\n      }\n    }\n  }\n\n  private def performCaretBam(width: Double) = {\n    if (lastPositions.nonEmpty) {\n      editor.get.foreach { editor =>\n        val myLastPositions = lastPositions\n        SwingUtilities.invokeLater(() => {\n          myLastPositions.foreach {\n            case (a, b) =>\n              val w = editor.getComponent.getWidth.toDouble\n              val h = editor.getComponent.getHeight.toDouble\n              initializeAnimation(a,\n                                  new Point(math.min(0, b.x), math.min(0, b.y)),\n                                  width)\n          }\n        })\n      }\n    }\n  }\n\n  def getAllCaretPositions: Seq[Point] = {\n\n    editor.get.toList.flatMap { editor =>\n      editor.getCaretModel.getAllCarets.asScala.toSeq.map(caret =>\n        Util.getPoint(caret.getVisualPosition, caret.getEditor))\n    }\n  }\n\n  def updateElementsOfPower(): Unit = {\n    var delta = (System.currentTimeMillis() - lastUpdate)\n    val value = (1000.0 / powerMode.frameRate.toHertz)\n    if (delta > value * 2) {\n      //smoothen movement when frame rate drops\n      delta = 16\n    }\n    lastUpdate = System.currentTimeMillis()\n    val db: Double = 1000.0 / 16\n    if (elementsOfPower.nonEmpty) {\n      elementsOfPower =\n        elementsOfPower.filterNot(p => p._1.update((delta / db).toFloat))\n      repaint()\n    }\n  }\n\n  def addPowerIndicator(): Unit = {\n    val indicatorWidth = 100\n    elementsOfPower :+= (PowerIndicator(\n      (getMyBounds.width - 20 - indicatorWidth).toFloat,\n      (getMyBounds.height - 20 - indicatorWidth).toFloat,\n      indicatorWidth.toFloat,\n      indicatorWidth.toFloat,\n      1000L,\n      editor\n    ), getScrollPosition)\n  }\n\n  def initializeAnimation(point: Point): Unit = {\n\n    this.setBounds(getMyBounds)\n\n    if (powerMode.isSparksEnabled) {\n      addSparks(point)\n    }\n    if (powerMode.isFlamesEnabled) {\n      addFlames(point)\n    }\n\n    if (powerMode.isShakeEnabled) {\n      doShake(shakeComponents)\n    }\n    repaint()\n\n  }\n\n  def initializeAnimation(a: Point, b: Point, lineWidth: Double): Unit = {\n    val x = a.x\n    var y = a.y\n    val width = math.max(b.x - x, 50)\n    val height = math.max(b.y - y, 50)\n    val dim =\n      (Seq(\n        Seq(lineWidth.toInt, width, height, 50).max,\n        editor.get.get.getComponent.getWidth,\n        editor.get.get.getComponent.getHeight).min * powerMode.valueFactor).toInt\n    if (b.y - y.abs < dim) {\n      y = y - dim / 2\n    }\n    elementsOfPower :+= (PowerBam(\n      math.max(0, x).toFloat,\n      math.max(0, y).toFloat,\n      dim.toFloat,\n      dim.toFloat,\n      (powerMode.bamLife * powerMode.valueFactor).toMilliseconds.toLong), getScrollPosition)\n  }\n\n  def addFlames(point: Point): Unit = {\n    val base = 0.3\n    val wh = (powerMode.maxFlameSize * base +\n      ((math.random * powerMode.maxFlameSize * (1 - base)) * powerMode.valueFactor)).toInt\n    val initLife =\n      (powerMode.maxFlameLife * powerMode.valueFactor).toMilliseconds.toInt\n    if (initLife > 100) {\n      elementsOfPower :+= (PowerFlame(point.x + 5,\n                                      point.y - 1,\n                                      wh,\n                                      wh,\n                                      initLife,\n                                      true), getScrollPosition)\n      elementsOfPower :+= (PowerFlame(point.x + 5,\n                                      point.y + 15,\n                                      wh,\n                                      wh,\n                                      initLife,\n                                      false), getScrollPosition)\n    }\n  }\n\n  def addSparks(point: Point): Unit = {\n    for (i <- 0 to (powerMode.sparkCount * powerMode.valueFactor).toInt) {\n      addSpark(point.x, point.y)\n    }\n  }\n\n  def addSpark(x: Int, y: Int): Unit = {\n    val dx\n      : Double = (Math.random * 2) * (if (Math.random > 0.5) -1 else 1) * powerMode.sparkVelocityFactor\n    val dy: Double = ((Math.random * -3) - 1) * powerMode.sparkVelocityFactor\n    val size = ((Math.random * powerMode.sparkSize) + 1).toInt\n    val life = Math.random() * powerMode.getSparkLife * powerMode.valueFactor\n    val powerSpark = PowerSpark(x.toFloat,\n                                y.toFloat,\n                                dx.toFloat,\n                                dy.toFloat,\n                                size.toFloat,\n                                life.toLong,\n                                genNextColor,\n                                powerMode.gravityFactor.toFloat)\n    elementsOfPower :+= (powerSpark, getScrollPosition)\n  }\n\n  def genNextColor: PowerColor =\n    (getColorPart(powerMode.getRedFrom, powerMode.getRedTo),\n     getColorPart(powerMode.getGreenFrom, powerMode.getGreenTo),\n     getColorPart(powerMode.getBlueFrom, powerMode.getBlueTo),\n     powerMode.getColorAlpha / 255f)\n\n  def getColorPart(from: Int, to: Int): Float = {\n    (((Math.random() * (to - from)) + from) / 255).toFloat\n  }\n\n  def getScrollPosition = (\n    editor.get.get.getScrollingModel.getHorizontalScrollOffset,\n    editor.get.get.getScrollingModel.getVerticalScrollOffset\n  )\n\n  def doShake(myShakeComponents: Seq[JComponent]): Unit = {\n    if (Util.editorOk(editor.get.get, 100)) {\n      shakeData = shakeData match {\n        case Some((dx, dy, scrollX, scrollY)) =>\n          myShakeComponents.foreach { myShakeComponent =>\n            val bounds: Rectangle = myShakeComponent.getBounds\n            myShakeComponent.setBounds(bounds.x + dx,\n                                       bounds.y + dy,\n                                       bounds.width,\n                                       bounds.height)\n          }\n          None\n        case None =>\n          val dx = generateShakeOffset\n          val dy = generateShakeOffset\n          val scrollX =\n            editor.get.get.getScrollingModel.getHorizontalScrollOffset\n          val scrollY = editor.get.get.getScrollingModel.getVerticalScrollOffset\n          myShakeComponents.foreach { myShakeComponent =>\n            val bounds: Rectangle = myShakeComponent.getBounds\n            myShakeComponent.setBounds(bounds.x + dx,\n                                       bounds.y + dy,\n                                       bounds.width,\n                                       bounds.height)\n          }\n          Some((-dx, -dy, scrollX, scrollY))\n      }\n      lastShake = System.currentTimeMillis()\n    }\n  }\n\n  def generateShakeOffset: Int = {\n    val range = powerMode.shakeRange * powerMode.valueFactor\n    (range - (Math.random * 2 * range)).toInt\n  }\n\n  def componentResized(e: ComponentEvent): Unit = {\n    setBounds(getMyBounds)\n    logger.trace(\"Resized\")\n  }\n\n  def componentMoved(e: ComponentEvent): Unit = {\n    setBounds(getMyBounds)\n    logger.trace(\"Moved\")\n  }\n\n  def getMyBounds: Rectangle = {\n    val area = editor.get.get.getScrollingModel.getVisibleArea\n    val rectangle = new Rectangle(area.x, area.y, area.width, area.height)\n    rectangle\n  }\n\n  def componentShown(e: ComponentEvent): Unit = {}\n\n  def componentHidden(e: ComponentEvent): Unit = {}\n\n  protected override def paintComponent(g: Graphics): Unit = {\n    super.paintComponent(g)\n    if (powerMode.isEnabled) {\n      if (shakeData.isDefined &&\n          System.currentTimeMillis() - lastShake > 100 &&\n          shakeData.get._1.abs < 50 && shakeData.get._2.abs < 50) {\n        doShake(Seq(editor.get.get.getComponent))\n      }\n      renderElementsOfPower(g)\n    }\n  }\n\n  def renderElementsOfPower(g: Graphics): Unit = {\n    val scrollingModel: ScrollingModel = editor.get.get.getScrollingModel\n    val xyNew = (\n      scrollingModel.getHorizontalScrollOffset,\n      scrollingModel.getVerticalScrollOffset\n    )\n\n    elementsOfPower.foreach { pp =>\n      val (elementOfPower, (x, y)) = pp\n      val dxx = x - xyNew._1\n      val dyy = y - xyNew._2\n      elementOfPower.render(g, dxx, dyy)\n    }\n\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/management/ElementOfPowerContainerManager.scala",
    "content": "/*\n * Copyright 2015 Baptiste Mesta\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 */\npackage de.ax.powermode.power.management\n\nimport com.intellij.openapi.actionSystem.{\n  CommonDataKeys,\n  DataConstants,\n  DataContext,\n  PlatformCoreDataKeys,\n  PlatformDataKeys\n}\nimport com.intellij.openapi.editor.Editor\nimport com.intellij.openapi.editor.event.{\n  EditorFactoryEvent,\n  EditorFactoryListener\n}\nimport com.intellij.openapi.fileEditor.FileEditorManager\nimport com.intellij.openapi.project.Project\nimport de.ax.powermode.power.sound.PowerSound\nimport de.ax.powermode.{Power, PowerMode, Util}\n\nimport java.awt._\nimport javax.swing._\nimport scala.collection.mutable\nimport scala.language.postfixOps\nimport scala.util.{Failure, Success, Try}\nimport com.ryanstull.nullsafe._\n\nimport scala.ref.WeakReference\n\n/**\n  * @author Baptiste Mesta\n  */\nclass ElementOfPowerContainerManager extends EditorFactoryListener with Power {\n  def ForceTry[X](f: => X): Try[X] = {\n    try {\n      Success(f).filter(_ != null)\n    } catch {\n      case e: Throwable =>\n        e.printStackTrace()\n        logger.debug(\"info doing ForceTry\", e)\n        Failure(e)\n    }\n  }\n\n  /**\n    * editor.hashcode -> elementOfPowerContainer\n    */\n  private val elementsOfPowerContainers\n    : mutable.WeakHashMap[Editor, WeakReference[ElementOfPowerContainer]] =\n    mutable.WeakHashMap.empty\n\n  private lazy val triedSound: Try[PowerSound] =\n    powerMode.mediaPlayerExists.flatMap { _ =>\n      Try {\n        new PowerSound(powerMode.soundsFolder,\n                       powerMode.valueFactor,\n                       (powerMode.minVolume, powerMode.maxVolume))\n      }\n\n    }\n  lazy val sound = synchronized { triedSound }\n\n  def showIndicator(dataContext: DataContext): Unit = {\n    if (powerMode.powerIndicatorEnabled && powerMode.isEnabled) {\n      val maybeProject: Seq[Project] = Seq(ForceTry {\n        dataContext.getData(CommonDataKeys.PROJECT)\n      }, ForceTry {\n        dataContext.getData(CommonDataKeys.PROJECT)\n      }).to(LazyList).flatMap { o =>\n        o.toOption.flatMap(Option(_)).map(_.asInstanceOf[Project])\n      }\n      maybeProject.headOption.foreach(p => {\n        val textEditor: Editor =\n          FileEditorManager.getInstance(p).getSelectedTextEditor\n\n        SwingUtilities.invokeLater(() => {\n          opt(textEditor)\n            .flatMap(elementsOfPowerContainers.get)\n            .flatMap(_.get)\n            .foreach(_.addPowerIndicator())\n        })\n      })\n    }\n  }\n\n  val elementsOfPowerUpdateThread = new Thread(new Runnable() {\n    def run: Unit = {\n      while (true) {\n        try {\n          if (powerMode != null) {\n            powerMode.reduceHeatup\n            updateSound\n            updateContainers\n            try {\n              Thread.sleep((1000 / powerMode.frameRate.toHertz) toInt)\n            } catch {\n              case ignored: InterruptedException => {}\n            }\n          }\n        } catch {\n          case e: Throwable => PowerMode.logger.debug(e.getMessage, e)\n        }\n      }\n    }\n\n    def updateContainers: Unit = {\n      elementsOfPowerContainers.values\n        .flatMap(_.get)\n        .foreach(_.updateElementsOfPower())\n    }\n\n    var soundErrorLogged = System.currentTimeMillis()\n\n    def updateSound: Unit = {\n      try {\n        if (powerMode.isEnabled &&\n            powerMode.soundsFolder.exists(f => f.exists() && f.isDirectory)\n            && powerMode.isSoundsPlaying) {\n          if (sound.isFailure && soundErrorLogged + 5000 < System\n                .currentTimeMillis()) {\n            logger.debug(sound.failed.get.getMessage, sound.failed.get)\n            soundErrorLogged += 1\n          }\n          sound.foreach(_.play())\n        } else {\n          sound.foreach(_.stop())\n        }\n        sound.foreach(_.setVolume(powerMode.valueFactor))\n      } catch {\n        case e: Throwable =>\n          logger.debug(e.getMessage, e)\n      }\n    }\n  })\n  elementsOfPowerUpdateThread.start()\n\n  override def editorCreated(event: EditorFactoryEvent): Unit = {\n    val editor: Editor = event.getEditor\n    val isActualEditor = Try {\n      Util.isActualEditor(editor)\n    }.getOrElse(false)\n    if (isActualEditor) {\n      opt(editor)\n        .flatMap(\n          editor =>\n            elementsOfPowerContainers\n              .put(editor,\n                   WeakReference(\n                     new ElementOfPowerContainer(WeakReference(editor)))))\n    }\n  }\n\n  override def editorReleased(event: EditorFactoryEvent): Unit = {\n    opt(event.getEditor)\n      .flatMap(elementsOfPowerContainers.remove)\n\n  }\n\n  def initializeAnimation(editor: Editor, pos: Point): Unit = {\n    if (powerMode.isEnabled) {\n      SwingUtilities.invokeLater(new Runnable() {\n        def run: Unit = {\n          initializeInUI(editor, pos)\n        }\n      })\n    }\n  }\n\n  private def initializeInUI(editor: Editor, pos: Point): Unit = {\n    opt(editor)\n      .flatMap(elementsOfPowerContainers.get)\n      .flatMap(_.get)\n      .foreach(_.initializeAnimation(pos))\n  }\n\n  def dispose: Unit = {\n    elementsOfPowerUpdateThread.interrupt()\n    elementsOfPowerContainers.clear()\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/sound/MediaPlayer.scala",
    "content": "package de.ax.powermode.power.sound\n\nimport com.intellij.openapi.diagnostic.Logger\nimport de.ax.powermode.PowerMode\nimport javazoom.jl.player.{FactoryRegistry, HackyJavaSoundAudioDevice}\nimport javazoom.jl.player.advanced.{\n  AdvancedPlayer,\n  PlaybackEvent,\n  PlaybackListener\n}\nimport squants.Dimensionless\nimport squants.DimensionlessConversions.dimensionlessToDouble\n\nimport scala.util.{Try, Using}\nimport java.io.{\n  BufferedInputStream,\n  File,\n  FileInputStream,\n  FileOutputStream,\n  InputStream\n}\nimport javax.sound.sampled.{Control, FloatControl}\n\nobject MediaPlayer {\n  def getSoundAudioDevice =\n    new HackyJavaSoundAudioDevice\n\n}\n\nclass MediaPlayer(file: File, volumeRange: => (Dimensionless, Dimensionless))\n    extends AutoCloseable {\n  def logger: Logger = PowerMode.logger\n  val stream: BufferedInputStream = new BufferedInputStream(\n    new FileInputStream(file))\n  val soundAudioDevice: HackyJavaSoundAudioDevice =\n    MediaPlayer.getSoundAudioDevice\n  val player: AdvancedPlayer = new AdvancedPlayer(stream, soundAudioDevice)\n  val listener: PlaybackListener = new PlaybackListener {\n    override def playbackStarted(evt: PlaybackEvent): Unit = {\n      logger.debug(\"playbackStarted\")\n    }\n\n    override def playbackFinished(evt: PlaybackEvent): Unit = {\n      notifyHandlers()\n    }\n  }\n  var playThread = Option.empty[Thread]\n  player.setPlayBackListener(listener)\n\n  def setVolume(rawGain: Dimensionless): Unit = {\n    logger.trace(\"setting volume \")\n    val control: Option[FloatControl] = Option(soundAudioDevice.source)\n      .flatMap(sourceDataLine =>\n        Try {\n          sourceDataLine.getControl(FloatControl.Type.MASTER_GAIN)\n        }.toOption)\n      .map(_.asInstanceOf[FloatControl])\n    control.foreach { volControl =>\n      val range: (Dimensionless, Dimensionless) = volumeRange\n      val volRange = volControl\n        .getMaximum() - volControl.getMinimum()\n\n      val gain: Dimensionless =\n        if (range._2 < rawGain) {\n          range._2\n        } else if (rawGain < range._1) {\n          range._1\n        } else {\n          rawGain\n        }\n\n      // use log scale to have a smoother transition at higer volume level\n      // slight higher volume changes are much harsher compared to the same amount of low volume change otherwise.\n      val logGain: Double = math.log10(1 + gain.toDouble * 9)\n      val newGain: Double =\n        Math.min(Math.max(volControl.getMinimum() + (logGain * volRange),\n                          volControl.getMinimum()),\n                 volControl.getMaximum() * 0.99999999)\n\n      logger.trace(\n        s\"setting volume ${rawGain}factor. was limited to ${gain} applied to ${volControl\n          .getMinimum()} - ${volControl.getMaximum()}  => ${newGain}\")\n      logger.trace(\"Was: \" + volControl.getValue() + \" Will be: \" + newGain);\n      volControl.setValue(newGain.toFloat);\n    }\n  }\n\n  def play(): Unit = {\n    if (playThread.isEmpty) {\n      logger.debug(\"starting\")\n      playThread = Option(new Thread(new Runnable() {\n        override def run(): Unit = {\n          try {\n            player.play()\n          } catch {\n            case e: Throwable =>\n              logger.debug(\"playback info\", e)\n              notifyHandlers()\n              throw e\n          } finally {\n            playThread = None\n          }\n        }\n      }))\n      playThread.foreach(_.start())\n      logger.debug(\"started\")\n\n    }\n  }\n\n  private def notifyHandlers(): Unit = {\n    handlers.foreach(_.apply())\n  }\n\n  def stop(): Unit = {\n    if (player != null) {\n      try {\n        logger.debug(\"stopping\")\n        player.stop()\n        logger.debug(\"stopped\")\n      } catch {\n        case e: Exception =>\n          logger.debug(\"info stopping\", e)\n\n      }\n    }\n  }\n  var handlers = List.empty[() => Unit]\n  def onError(fn: () => Unit): Unit = {\n    handlers ::= fn\n  }\n  def close(): Unit = {\n    try {\n      stop()\n    } finally {\n      player.close()\n      stream.close()\n    }\n  }\n}\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/sound/PowerSound.scala",
    "content": "package de.ax.powermode.power.sound\n\nimport de.ax.powermode.Power\nimport javazoom.jl.player.{FactoryRegistry, HackyJavaSoundAudioDevice, Player}\nimport squants.Dimensionless\n\nimport java.io.File\nimport scala.language.postfixOps\n\n/**\n  * Created by nyxos on 03.10.16.\n  */\nclass PowerSound(folder: => Option[File],\n                 valueFactor: => Dimensionless,\n                 volumeRange: => (Dimensionless, Dimensionless))\n    extends Power {\n  def next(): Unit = {\n    this.synchronized {\n      doStop()\n      doPlay()\n    }\n  }\n\n  def resetPlaying(): Unit = {\n    playing = false\n  }\n\n  def files: Array[File] =\n    folder\n      .flatMap(f => Option(f.listFiles()))\n      .getOrElse(Array.empty[File])\n      .filter(f => f.isFile && f.exists)\n\n  var playing = false\n\n  var current = 1\n\n  def setVolume(v: Dimensionless): Unit = this.synchronized {\n    mediaPlayer.foreach(_.setVolume(v))\n  }\n\n  private def doStop(): Unit = {\n    this.synchronized {\n      mediaPlayer.foreach(_.stop())\n      while (mediaPlayer.exists(_.playThread.exists(_.isAlive))) {\n        logger.debug(\"still playing in thread\")\n        Thread.sleep(100)\n      }\n      mediaPlayer = Option.empty\n      playing = false\n    }\n  }\n\n  var mediaPlayer = Option.empty[MediaPlayer]\n\n  var index = 0\n\n  var lastFolder: Option[File] = folder\n\n  def stop(): Unit = this.synchronized {\n    doStop()\n  }\n\n  def play(): Unit = this.synchronized {\n    if (lastFolder.map(_.getAbsolutePath) != folder.map(_.getAbsolutePath)) {\n      doStop()\n    }\n    doPlay()\n  }\n\n  private def doPlay(): Unit = {\n    val myFiles: Array[File] = files\n    if (!playing && myFiles != null && !myFiles.isEmpty) {\n      index = (Math.random() * (200 * myFiles.length)).toInt % myFiles.length\n      val f = myFiles(index)\n      logger.debug(\n        s\"${this.hashCode()} playing sound file '$f' playing=${playing} mediaPlayer=${mediaPlayer}\")\n      try {\n        playing = true\n        mediaPlayer = Some {\n          val mediaPlayer =\n            new de.ax.powermode.power.sound.MediaPlayer(f, volumeRange)\n          mediaPlayer.onError(() => {\n            logger.debug(\"resetting\")\n            resetPlaying()\n          })\n          mediaPlayer.setVolume(valueFactor)\n          mediaPlayer.play()\n          mediaPlayer\n        }\n        logger.debug(s\"started playing '$f'\")\n      } catch {\n        case e: Throwable =>\n          e.printStackTrace()\n          playing = false\n      }\n    }\n  }\n}\n"
  }
]