master b95c63edd88b cached
41 files
204.4 KB
50.5k tokens
48 symbols
1 requests
Download .txt
Showing preview only (219K chars total). Download the full file or copy to clipboard to get everything.
Repository: axaluss/power-mode-intellij-plugin
Branch: master
Commit: b95c63edd88b
Files: 41
Total size: 204.4 KB

Directory structure:
gitextract_08n_przv/

├── .gitignore
├── .scalafmt.conf
├── LICENSE
├── README.md
├── build.sbt
├── log4j.xml
├── project/
│   ├── build.properties
│   └── plugins.sbt
├── resources/
│   └── META-INF/
│       └── plugin.xml
└── src/
    └── main/
        ├── java/
        │   ├── de/
        │   │   └── ax/
        │   │       └── powermode/
        │   │           └── power/
        │   │               ├── color/
        │   │               │   ├── ColorViewController.java
        │   │               │   ├── MultiGradientPanel.java
        │   │               │   ├── UiTest.form
        │   │               │   └── UiTest.java
        │   │               └── ui/
        │   │                   ├── PowerModeConfigurableUI.form
        │   │                   ├── PowerModeConfigurableUI.java
        │   │                   └── ValueSettable.java
        │   └── javazoom/
        │       └── jl/
        │           └── player/
        │               └── HackyJavaSoundAudioDevice.java
        └── scala/
            └── de/
                └── ax/
                    └── powermode/
                        ├── ImageUtil.scala
                        ├── MyCaretListener.scala
                        ├── MyTypedActionHandler.scala
                        ├── NextSongAction.scala
                        ├── Power.scala
                        ├── PowerMode.scala
                        ├── PowerModeConfigurable.scala
                        ├── PowerModeStartup.scala
                        ├── TogglePowerMode.scala
                        ├── Util.scala
                        ├── cache/
                        │   └── Cache.scala
                        ├── package.scala
                        └── power/
                            ├── ElementOfPower.scala
                            ├── color/
                            │   ├── ColorEdges.scala
                            │   └── MyPaint.scala
                            ├── element/
                            │   ├── PowerBam.scala
                            │   ├── PowerFlame.scala
                            │   ├── PowerIndicator.scala
                            │   └── PowerSpark.scala
                            ├── hotkeys/
                            │   └── HotkeyHeatupListener.scala
                            ├── management/
                            │   ├── ElementOfPowerContainer.scala
                            │   └── ElementOfPowerContainerManager.scala
                            └── sound/
                                ├── MediaPlayer.scala
                                └── PowerSound.scala

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.idea
out
*.iml
*.jar
lib/
*.zip
**/target
.bsp/


================================================
FILE: .scalafmt.conf
================================================


================================================
FILE: LICENSE
================================================
Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================
Power Mode II Intellij plugin
======================

[![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)

![Demo](/images/powerMode.gif)

Installation
--------------
[Watch the Video](https://www.youtube.com/watch?v=aIWs7YQ9aMs)

[Install from Jetbrains plugin repositories](https://plugins.jetbrains.com/plugin/8251)

How to use
---------

Install the plugin then simply enable the sparkling in Preferences > Appearance > Power mode II

## Features

<ul>
    <li>Exploding falling sparks</li>
    <li>Editor shaking</li>
    <li>Flames</li>
    <li>Heatup based on typing speed. The more you type the more happens.</li>
    <li>Keyboard shortcut to toggle power mode [shift ctrl alt O]</li>
    <li>Choose particle colors and transparency within a color space</li>
    <li>Adjust particle velocity and gravitation</li>
    <li>Modify the animation frame rate</li>
    <li>Multi caret support</li>
    <li>Animation on caret movement</li>
    <li>Play music folder: volume based on heatup</li>
    <li>Play next song action: [shift ctrl alt M]</li>
    <li>Visualize bigger file editing with "BAM!"</li>
    <li>See your power level in the indicator box</li>
    <li>Customizable animation images</li>
    <li>Everything is configurable</li>
</ul>

<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"/>
Latest Release Download</a>
<br/>

<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"/>
Want to Donate a Beer?</a>

## Plugin Development Setup

1. install scala intellij plugin
2. import the sbt project (`build.sbt`)
3. follow the docs [here](https://github.com/JetBrains/sbt-idea-plugin)
4. create the plugin artifact `sbt packageArtifactZip`
5. install in intellij

## "Architecture"

* `PowerMode` is the settings instance which is used by `PowerModeConfigurable` to populate the UI Settings dialog.
  `PowerModeConfigurableUI` manages the settings dialog to change the settings in `PowerMode`.
* `PowerMode` is stored/loaded by xml serializer and annotation magic by Intellij.
* `PowerMode` starts up the `SparkContainerManager`. The `SparkContainerManager` creates a `SparkContainer` for each
  editor.
* The `SparkContainer` creates the `ElementOfPower` (`PowerSpark, PowerFlame`) and manages their animation and
  lifecycle.

### heatup

* heatup increases the lifetime and amount of Sparks and Flames over time. The most values are multiplied
  with `ElementOfPower.valueFactor` to simulate this heatup.
  `ElementOfPower.valueFactor` is composed of `heatupFactor` (how much of all animation doesn't depend on heatup)
  and `timeFactor` (how much heatup do we currently have).
* The heatup itself is calculated by `keyStrokesPerMinute` and the amount of keystrokes within `heatupTime`.


================================================
FILE: build.sbt
================================================
import org.jetbrains.sbtidea.Keys._

lazy val powerMode =
  project
    .in(file("."))
    .enablePlugins(SbtIdeaPlugin)
    .settings(
      version := "105.501",
      scalaVersion := "2.13.12",
      ThisBuild / intellijPluginName := "Power Mode II",
      ThisBuild / intellijBuild := "232.10227.8",
      ThisBuild / intellijPlatform := IntelliJPlatform.IdeaCommunity,
      Global / intellijAttachSources := true,
      Compile / javacOptions ++= "--release" :: "17" :: Nil,
      intellijPlugins += "com.intellij.properties".toPlugin,
      libraryDependencies ++= Seq(
        "javazoom" % "jlayer" % "1.0.1",
        "org.typelevel" %% "squants" % "1.6.0",
        "org.apache.commons" % "commons-math3" % "3.3",
        "com.eclipsesource.minimal-json" % "minimal-json" % "0.9.5" withSources ()
      ),
      libraryDependencies += "com.ryanstull" %% "scalanullsafe" % "1.2.6",
      scalacOptions in ThisBuild += "-deprecation",
      unmanagedJars in Compile += baseDirectory.value / "lib",
      unmanagedResourceDirectories in Compile += baseDirectory.value / "resources",
      resourceDirectories in Runtime += baseDirectory.value / "resources",
      unmanagedResourceDirectories in Test += baseDirectory.value / "testResources",
      packageMethod := PackagingMethod.Standalone(),
      bundleScalaLibrary in ThisBuild := true
    )


================================================
FILE: log4j.xml
================================================
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="[%p] %c %M - %m%n"/>
        </layout>
    </appender>

    <category name="de.ax.powermode">
        <priority value="trace"/>
        <appender-ref ref="console"/>
    </category>

    <category name="com.intellij">
        <priority value="info"/>
        <appender-ref ref="console"/>
    </category>


</log4j:configuration>

================================================
FILE: project/build.properties
================================================
sbt.version=1.4.3


================================================
FILE: project/plugins.sbt
================================================
addSbtPlugin("org.jetbrains" % "sbt-idea-plugin" % "3.18.3")


================================================
FILE: resources/META-INF/plugin.xml
================================================
<idea-plugin>
    <id>de.ax.powermode</id>
    <name>Power Mode II</name>
    <version>105.501</version>
    <vendor email="axaluss@gmail.com" url="https://github.com/axaluss/power-mode-intellij-plugin">Alexander Thom
    </vendor>
    <description><![CDATA[
        <h1>Power Mode</h1>
        <span>Based on the activate-power-mode atom plugin and forked from Baptiste Mesta on Github.</span>
        <h2>Features</h2>
        <ul>
            <li>Exploding falling sparks</li>
            <li>Editor shaking</li>
            <li>Flames</li>
            <li>Heatup based on typing speed. The more you type the more happens.</li>
            <li>Keyboard shortcut to toggle power mode [shift ctrl alt O]</li>
            <li>Choose particle colors and transparency within a color space</li>
            <li>Adjust particle velocity and gravitation</li>
            <li>Modify the animation frame rate</li>
            <li>Multi caret support</li>
            <li>Animation on caret movement</li>
            <li>Play music folder: volume based on heatup</li>
            <li>Play next song action: [shift ctrl alt M]</li>
            <li>Visualize bigger file editing with "BAM!"</li>
            <li>See your power level in the indicator box</li>
            <li>Customizable animation images</li>
            <li>Everything is configurable</li>
        </ul>
        <h2>Usage</h2>
        <ol>
            <li>Install the plugin</li>
            <li>ENTER POWER MODE in Preferences > Appearance > Power mode II</li>
            <li>CHANGE THE SLIDERS and options to your liking</li>
        </ol>

        <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"/>
            Latest Release Download</a>
        <br/>
<h2>latest changes </h2>
fixes
 <ul>
    <li>#67 hashCode NPE</li>
    <li>#64 Framerate settings is always set to default</li>
    <li>#65 Not compatible with the version IntelliJ IDEA 2023.2.3</li>
    <li>#66 hold references to disposed objects</li>
    <li>#60 When enabled, inline git diff is not clickable</li>
</ul>
        <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"/>
            Want to pass me a Beer?
        </a>
        ]]></description>

    <idea-version since-build="232"/>

    <depends>com.intellij.modules.platform</depends>


    <extensions defaultExtensionNs="com.intellij">
        <applicationConfigurable groupId="appearance" groupWeight="20" id="power.mode.ii" displayName="Power Mode II"
                                 instance="de.ax.powermode.PowerModeConfigurable"/>
        <applicationService serviceImplementation="de.ax.powermode.PowerMode"/>
    </extensions>

    <applicationListeners>
        <listener class="de.ax.powermode.PowerModeStartup" topic="com.intellij.ide.AppLifecycleListener"/>
    </applicationListeners>

    <actions>

        <action id="togglePowerModeII" class="de.ax.powermode.TogglePowerMode" text="Toggle Power Mode II"
                description="Toggle Power Mode II">
            <add-to-group group-id="ToolsMenu" anchor="last"/>
            <keyboard-shortcut keymap="$default" first-keystroke="shift ctrl alt O"/>
        </action>
        <action id="powerModeIInextSong" class="de.ax.powermode.NextSongAction" text="next Power Mode song"
                description="next Power Mode song">
            <add-to-group group-id="ToolsMenu" anchor="last"/>
            <keyboard-shortcut keymap="$default" first-keystroke="shift ctrl alt M"/>
        </action>
    </actions>

</idea-plugin>

================================================
FILE: src/main/java/de/ax/powermode/power/color/ColorViewController.java
================================================
package de.ax.powermode.power.color;

import de.ax.powermode.PowerMode;

/**
 * Created by nyxos on 05.07.16.
 */
public class ColorViewController {
    private final PowerMode powerMode;
    double c = 0;
    double f = 60.0;
    //    double x = (255 / 5000.0) * f;
    int dir = 1;

    public double genX() {
        return dir * ((powerMode.getBlueTo() - powerMode.getBlueFrom()) / 5000.0) * f;
    }

    public ColorViewController(MultiGradientPanel colorView, PowerMode powerMode) {
        this.powerMode = powerMode;
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (colorView.isVisible()) {
                    long t0 = System.currentTimeMillis();
                    c = Math.max(Math.min((c + genX()), powerMode.blueTo()), powerMode.blueFrom());
                    if (c >= powerMode.blueTo()) {
                        c = powerMode.blueTo();
                        dir *= -1;
                    }
                    if (c <= powerMode.blueFrom()) {
                        c = powerMode.blueFrom();
                        dir *= -1;
                    }
                    colorView.doUpdate(c);
                    colorView.repaint();
                    try {
                        Thread.sleep((long) (Math.max(0, (1000 / f) - (System.currentTimeMillis() - t0))));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread.start();
    }
}


================================================
FILE: src/main/java/de/ax/powermode/power/color/MultiGradientPanel.java
================================================
package de.ax.powermode.power.color;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Point2D;


public class MultiGradientPanel extends JPanel {
    int size;

    public void setColorEdges(ColorEdges colorEdges) {
        this.colorEdges = colorEdges;
    }

    private ColorEdges colorEdges;


    public MultiGradientPanel(int size, ColorEdges colorEdges) {
        super();
        this.size = size;
        this.colorEdges = colorEdges;
        this.setPreferredSize(new Dimension(size, size));
    }


    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        GradientPaint twoColorGradient = new GradientPaint(
                size, 0f, colorEdges.getRightTop(), 0, size, colorEdges.getLeftBottom());

        float radius = size - (size / 4.0f);
        float[] dist = {0f, 1.0f};
        Point2D center = new Point2D.Float(0f, 0f);
        Color noColor = new Color(0f, 0f, 0f, 0f);
        Color[] colors = {colorEdges.getLeftTop(), noColor};
        RadialGradientPaint thirdColor = new RadialGradientPaint(center, radius, dist, colors);


        center = new Point2D.Float(size, size);
        Color[] colors2 = {colorEdges.getRightBottom(), noColor};
        RadialGradientPaint fourthColor = new RadialGradientPaint(center, radius, dist, colors2);

        g2d.setPaint(twoColorGradient);
        g2d.fillRect(0, 0, size, size);

        g2d.setPaint(thirdColor);
        g2d.fillRect(0, 0, size, size);

        g2d.setPaint(fourthColor);
        g2d.fillRect(0, 0, size, size);
    }

    public void doUpdate(double c) {
        int c1 = (int) c;
        colorEdges.updateColors(c1);
    }


}

================================================
FILE: src/main/java/de/ax/powermode/power/color/UiTest.form
================================================
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.ax.powermode.power.color.UiTest">
  <grid id="27dc6" binding="root" layout-manager="BorderLayout" hgap="0" vgap="0">
    <constraints>
      <xy x="20" y="20" width="500" height="400"/>
    </constraints>
    <properties/>
    <border type="none"/>
    <children>
      <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">
        <margin top="0" left="0" bottom="0" right="0"/>
        <constraints border-constraint="Center"/>
        <properties/>
        <border type="none"/>
        <children/>
      </grid>
    </children>
  </grid>
</form>


================================================
FILE: src/main/java/de/ax/powermode/power/color/UiTest.java
================================================
package de.ax.powermode.power.color;

import javax.swing.*;
import java.awt.*;

/**
 * Created by nyxos on 21.06.16.
 */
public class UiTest {
    private JPanel colorView;
    private JPanel root;


    static double c = 0;
    static double f = 60.0;
    static double x = (255 / 5000.0) * f;

    public static void main(String[] args) {
        JFrame frame = new JFrame("UiTest");
        UiTest uiTest = new UiTest();
        frame.setContentPane(uiTest.root);
        frame.setSize(500, 500);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);


    }

    private void createUIComponents() {
//        colorView = new MultiGradientPanel(500, new ColorEdges());
//        new ColorViewController((MultiGradientPanel) colorView);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        root = new JPanel();
        root.setLayout(new BorderLayout(0, 0));
        root.add(colorView, BorderLayout.CENTER);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return root;
    }
}


================================================
FILE: src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.form
================================================
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.ax.powermode.power.ui.PowerModeConfigurableUI">
  <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">
    <margin top="0" left="0" bottom="0" right="0"/>
    <constraints>
      <xy x="20" y="-118" width="1091" height="1173"/>
    </constraints>
    <properties/>
    <border type="none"/>
    <children>
      <tabbedpane id="2ab37">
        <constraints>
          <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">
            <preferred-size width="200" height="200"/>
          </grid>
        </constraints>
        <properties>
          <tabLayoutPolicy value="0"/>
        </properties>
        <border type="none"/>
        <children>
          <grid id="c9d96" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
            <margin top="0" left="0" bottom="0" right="0"/>
            <constraints>
              <tabbedpane title="GENERAL OPTIONS"/>
            </constraints>
            <properties/>
            <border type="none"/>
            <children>
              <scrollpane id="59a36">
                <constraints>
                  <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"/>
                </constraints>
                <properties>
                  <enabled value="true"/>
                </properties>
                <border type="none"/>
                <children>
                  <grid id="27dc6" layout-manager="GridLayoutManager" row-count="19" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                    <margin top="0" left="0" bottom="0" right="0"/>
                    <constraints/>
                    <properties/>
                    <border type="none"/>
                    <children>
                      <component id="c1982" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="framerate"/>
                          <toolTipText value="particle &amp; flame updates per second"/>
                        </properties>
                      </component>
                      <component id="43211" class="javax.swing.JLabel" binding="frameRateValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="ddd7e" class="javax.swing.JSlider" binding="frameRate">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="120"/>
                          <minimum value="5"/>
                          <value value="30"/>
                        </properties>
                      </component>
                      <component id="2467a" class="javax.swing.JCheckBox" binding="powerModeEnabled">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="ENTER POWER MODE!"/>
                        </properties>
                      </component>
                      <component id="685dd" class="javax.swing.JCheckBox" binding="PARTICLESCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="SPARKS!"/>
                        </properties>
                      </component>
                      <component id="81466" class="javax.swing.JCheckBox" binding="shakeEnabled">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="SHAKE!"/>
                        </properties>
                      </component>
                      <component id="221d1" class="javax.swing.JCheckBox" binding="FLAMESCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="FLAMES!"/>
                        </properties>
                      </component>
                      <component id="97367" class="javax.swing.JCheckBox" binding="visualizeEveryCaretMovementCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="VISUALIZE EVERY CARET MOVEMENT!"/>
                          <toolTipText value="When disabled: only typing of letters will cause effects.&#10;When enabled: every caret movement will cause effects." noi18n="true"/>
                        </properties>
                      </component>
                      <component id="1f2a3" class="javax.swing.JCheckBox" binding="PLAYMUSICCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="PLAY MUSIC"/>
                          <toolTipText value="next song: shift ctrl alt M"/>
                        </properties>
                      </component>
                      <component id="d851e" class="javax.swing.JTextField" binding="soundsFolder">
                        <constraints>
                          <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">
                            <preferred-size width="150" height="-1"/>
                          </grid>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="f7cb8" class="javax.swing.JCheckBox" binding="BAMCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="BAM!"/>
                          <toolTipText value="visualize document changes with BAM!"/>
                        </properties>
                      </component>
                      <component id="4bca3" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="BAM! life [ms]"/>
                        </properties>
                      </component>
                      <component id="794d8" class="javax.swing.JLabel" binding="bamLifeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="f621e" class="javax.swing.JSlider" binding="bamLife">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10000"/>
                        </properties>
                      </component>
                      <component id="16478" class="javax.swing.JCheckBox" binding="PowerIndicatorCheckBox">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="POWER INDICATOR!"/>
                          <toolTipText value="Displays an imprecise visualization of the current heatup value."/>
                        </properties>
                      </component>
                      <component id="2456b" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="shake range [px]"/>
                          <toolTipText value="how many pixels should the shaking move?"/>
                        </properties>
                      </component>
                      <component id="fbfcb" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="min volume %"/>
                          <toolTipText value="how many pixels should the shaking move?"/>
                        </properties>
                      </component>
                      <component id="1246c" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="max volume %"/>
                          <toolTipText value="how many pixels should the shaking move?"/>
                        </properties>
                      </component>
                      <component id="a35ff" class="javax.swing.JLabel" binding="shakeRangeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="a2ce9" class="javax.swing.JLabel" binding="minVolumeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="4f3d8" class="javax.swing.JLabel" binding="maxVolumeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="d66bd" class="javax.swing.JSlider" binding="shakeRange">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="5b124" class="javax.swing.JSlider" binding="minVolume">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="e3988" class="javax.swing.JSlider" binding="maxVolume">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="72e7" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="max flame size [px]"/>
                          <toolTipText value="maximum flame size in pixels"/>
                        </properties>
                      </component>
                      <component id="afddc" class="javax.swing.JLabel" binding="maxFlameSizeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="acbf8" class="javax.swing.JSlider" binding="maxFlameSize">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="500"/>
                        </properties>
                      </component>
                      <component id="74982" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="flame life [ms]"/>
                          <toolTipText value="time to live for a flame in milliseconds"/>
                        </properties>
                      </component>
                      <component id="badbb" class="javax.swing.JLabel" binding="flameLifeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="321e2" class="javax.swing.JSlider" binding="flameLife">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10000"/>
                        </properties>
                      </component>
                      <component id="4ae70" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="hint: 'heatup base level' should be &lt;100%"/>
                        </properties>
                      </component>
                      <component id="ae24c" class="javax.swing.JCheckBox" binding="customFlameImages">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="custom flame images"/>
                          <toolTipText value="provide a folder with the images of a flame animation"/>
                        </properties>
                      </component>
                      <component id="f9586" class="javax.swing.JTextField" binding="flameImagesFolder">
                        <constraints>
                          <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">
                            <preferred-size width="150" height="-1"/>
                          </grid>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="b4da3" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="image folder:"/>
                        </properties>
                      </component>
                      <component id="b011a" class="javax.swing.JCheckBox" binding="customBamImages">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="custom BAM! images"/>
                          <toolTipText value="choose your own BAM! images"/>
                        </properties>
                      </component>
                      <component id="30044" class="javax.swing.JCheckBox" binding="animateBAMImagesCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="animate BAM! images"/>
                          <toolTipText value="will cycle through all BAM! images in the given folder and create an animation (like a GIF)."/>
                        </properties>
                      </component>
                      <component id="31962" class="javax.swing.JTextField" binding="bamImagesFolder">
                        <constraints>
                          <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">
                            <preferred-size width="150" height="-1"/>
                          </grid>
                        </constraints>
                        <properties/>
                      </component>
                      <component id="ebfd1" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="image folder:"/>
                        </properties>
                      </component>
                      <component id="1304a" class="javax.swing.JCheckBox" binding="HOTKEYHEATUPCheckBox" default-binding="true">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="HOTKEY HEATUP"/>
                          <toolTipText value="Disable if having problems with hotkey visualization"/>
                        </properties>
                      </component>
                      <component id="452c" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="!!! might interfere with autocompletion and other plugins/editors!" noi18n="true"/>
                        </properties>
                      </component>
                      <component id="64868" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="music folder:"/>
                        </properties>
                      </component>
                    </children>
                  </grid>
                </children>
              </scrollpane>
              <vspacer id="e124f">
                <constraints>
                  <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"/>
                </constraints>
              </vspacer>
            </children>
          </grid>
          <scrollpane id="23fd3">
            <constraints>
              <tabbedpane title="HEATUP"/>
            </constraints>
            <properties/>
            <border type="none"/>
            <children>
              <grid id="30a31" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                <margin top="0" left="0" bottom="0" right="0"/>
                <constraints/>
                <properties/>
                <border type="none" title="Heatup"/>
                <children>
                  <component id="81202" class="javax.swing.JLabel">
                    <constraints>
                      <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">
                        <preferred-size width="176" height="15"/>
                      </grid>
                    </constraints>
                    <properties>
                      <text value="heatup base level [%]"/>
                      <toolTipText value="the lower the level the fewer happens at the start of typing."/>
                    </properties>
                  </component>
                  <component id="bc55" class="javax.swing.JLabel" binding="heatupValue">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <text value="Label"/>
                    </properties>
                  </component>
                  <component id="50558" class="javax.swing.JSlider" binding="heatup">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties/>
                  </component>
                  <component id="4cf47" class="javax.swing.JLabel">
                    <constraints>
                      <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">
                        <preferred-size width="176" height="15"/>
                      </grid>
                    </constraints>
                    <properties>
                      <text value="heatup time [ms]"/>
                      <toolTipText value="time range in milliseconds. The count of keystrokes in this period is used to calculate heatup."/>
                    </properties>
                  </component>
                  <component id="addf7" class="javax.swing.JLabel" binding="heatupTimeValue">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <text value="Label"/>
                    </properties>
                  </component>
                  <component id="266a0" class="javax.swing.JSlider" binding="heatupTime">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <maximum value="60000"/>
                    </properties>
                  </component>
                  <component id="88552" class="javax.swing.JLabel">
                    <constraints>
                      <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">
                        <preferred-size width="176" height="15"/>
                      </grid>
                    </constraints>
                    <properties>
                      <text value="heatup threshold [%]"/>
                      <toolTipText value="how much heatup in % has to be reached until something happens"/>
                    </properties>
                  </component>
                  <component id="b9417" class="javax.swing.JLabel" binding="heatupThresholdValue">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <text value="Label"/>
                    </properties>
                  </component>
                  <component id="df601" class="javax.swing.JSlider" binding="heatupThreshold">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <maximum value="100"/>
                      <minimum value="0"/>
                      <value value="30"/>
                    </properties>
                  </component>
                  <component id="e564c" class="javax.swing.JLabel">
                    <constraints>
                      <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">
                        <preferred-size width="176" height="15"/>
                      </grid>
                    </constraints>
                    <properties>
                      <text value="keystrokes per minute"/>
                      <toolTipText value="used to calculate heatup"/>
                    </properties>
                  </component>
                  <component id="7cba5" class="javax.swing.JLabel" binding="keyStrokesPerMinuteValue">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <text value="Label"/>
                    </properties>
                  </component>
                  <component id="5af3" class="javax.swing.JSlider" binding="keyStrokesPerMinute">
                    <constraints>
                      <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"/>
                    </constraints>
                    <properties>
                      <maximum value="3000"/>
                      <value value="100"/>
                    </properties>
                  </component>
                  <component id="d3a6d" class="javax.swing.JTextArea">
                    <constraints>
                      <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">
                        <preferred-size width="150" height="50"/>
                      </grid>
                    </constraints>
                    <properties>
                      <editable value="false"/>
                      <enabled value="true"/>
                      <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"/>
                    </properties>
                  </component>
                  <vspacer id="87d17">
                    <constraints>
                      <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"/>
                    </constraints>
                  </vspacer>
                </children>
              </grid>
            </children>
          </scrollpane>
          <scrollpane id="8994b">
            <constraints>
              <tabbedpane title="SPARKS"/>
            </constraints>
            <properties/>
            <border type="none"/>
            <children>
              <grid id="eed8f" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                <margin top="0" left="0" bottom="0" right="0"/>
                <constraints/>
                <properties/>
                <border type="none"/>
                <children>
                  <grid id="40358" layout-manager="GridLayoutManager" row-count="16" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                    <margin top="0" left="0" bottom="0" right="0"/>
                    <constraints>
                      <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">
                        <preferred-size width="200" height="245"/>
                      </grid>
                    </constraints>
                    <properties/>
                    <border type="none" title="Sparks"/>
                    <children>
                      <component id="f3691" class="javax.swing.JLabel" binding="sparkColorRedFromValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="31348" class="javax.swing.JSlider" binding="sparkColorRedFrom">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <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">
                        <margin top="0" left="0" bottom="0" right="0"/>
                        <constraints>
                          <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">
                            <minimum-size width="200" height="200"/>
                            <preferred-size width="200" height="200"/>
                            <maximum-size width="200" height="200"/>
                          </grid>
                        </constraints>
                        <properties/>
                        <border type="none"/>
                        <children/>
                      </grid>
                      <component id="d622e" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="136" height="14"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark color red range"/>
                          <toolTipText value="how many sparks should appear?"/>
                        </properties>
                      </component>
                      <component id="941fc" class="javax.swing.JLabel" binding="sparkColorRedToValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="786cb" class="javax.swing.JSlider" binding="sparkColorRedTo">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="21559" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="spark color green range"/>
                          <toolTipText value="how many sparks should appear?"/>
                        </properties>
                      </component>
                      <component id="e4b78" class="javax.swing.JLabel" binding="sparkColorGreenFromValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="81e87" class="javax.swing.JSlider" binding="sparkColorGreenFrom">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="b5faf" class="javax.swing.JLabel" binding="sparkColorGreenToValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="ddc3c" class="javax.swing.JSlider" binding="sparkColorGreenTo">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="3e35c" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="spark color blue range"/>
                          <toolTipText value="how many sparks should appear?"/>
                        </properties>
                      </component>
                      <component id="30786" class="javax.swing.JLabel" binding="sparkColorBlueFromValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="cbe45" class="javax.swing.JSlider" binding="sparkColorBlueFrom">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="d73f" class="javax.swing.JLabel" binding="sparkColorBlueToValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="91c" class="javax.swing.JSlider" binding="sparkColorBlueTo">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="6e81a" class="javax.swing.JLabel">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="alpha"/>
                        </properties>
                      </component>
                      <component id="f8276" class="javax.swing.JLabel" binding="sparkColorAlphaValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="5402" class="javax.swing.JSlider" binding="sparkColorAlpha">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="255"/>
                        </properties>
                      </component>
                      <component id="2632e" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark count"/>
                          <toolTipText value="how many sparks should appear?"/>
                        </properties>
                      </component>
                      <component id="3b9ad" class="javax.swing.JLabel" binding="sparkCountValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="90a0" class="javax.swing.JSlider" binding="sparkCount">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="100"/>
                        </properties>
                      </component>
                      <component id="cd69f" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark life [ms]"/>
                          <toolTipText value="how many milliseconds should a spark live?"/>
                        </properties>
                      </component>
                      <component id="f5c2a" class="javax.swing.JLabel" binding="sparkLifeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="4f7ba" class="javax.swing.JSlider" binding="sparkLife">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10000"/>
                        </properties>
                      </component>
                      <component id="1b40f" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark size [px]"/>
                          <toolTipText value="spark size in pixels"/>
                        </properties>
                      </component>
                      <component id="b1591" class="javax.swing.JLabel" binding="sparkSizeValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="ded61" class="javax.swing.JSlider" binding="sparkSize">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10"/>
                        </properties>
                      </component>
                      <component id="c5412" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark velocity factor %"/>
                          <toolTipText value="100% is default spark velocity"/>
                        </properties>
                      </component>
                      <component id="c7259" class="javax.swing.JLabel" binding="velocityFactorValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="efd58" class="javax.swing.JSlider" binding="velocityFactor">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10000"/>
                          <minimum value="-10000"/>
                          <value value="100"/>
                        </properties>
                      </component>
                      <component id="3a93a" class="javax.swing.JLabel">
                        <constraints>
                          <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">
                            <preferred-size width="176" height="15"/>
                          </grid>
                        </constraints>
                        <properties>
                          <text value="spark gravity factor %"/>
                          <toolTipText value="100% is default spark gravity"/>
                        </properties>
                      </component>
                      <component id="5b27f" class="javax.swing.JLabel" binding="gravityFactorValue">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <text value="Label"/>
                        </properties>
                      </component>
                      <component id="108ab" class="javax.swing.JSlider" binding="gravityFactor">
                        <constraints>
                          <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"/>
                        </constraints>
                        <properties>
                          <maximum value="10000"/>
                          <minimum value="-10000"/>
                          <value value="100"/>
                        </properties>
                      </component>
                    </children>
                  </grid>
                  <vspacer id="11a93">
                    <constraints>
                      <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"/>
                    </constraints>
                  </vspacer>
                </children>
              </grid>
            </children>
          </scrollpane>
        </children>
      </tabbedpane>
    </children>
  </grid>
</form>


================================================
FILE: src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.java
================================================
package de.ax.powermode.power.ui;

import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import de.ax.powermode.PowerMode;
import de.ax.powermode.power.color.ColorViewController;
import de.ax.powermode.power.color.MultiGradientPanel;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.io.File;

/**
 * @author Baptiste Mesta
 */
public class PowerModeConfigurableUI implements ConfigurableUi<PowerMode> {


    private JPanel mainPanel;
    private JCheckBox powerModeEnabled;
    private JCheckBox shakeEnabled;
    private JSlider sparkCount;
    private JSlider sparkLife;
    private JSlider shakeRange;
    private JSlider heatup;
    private JSlider heatupTime;
    private JLabel sparkCountValue;
    private JLabel sparkLifeValue;
    private JLabel shakeRangeValue;
    private JLabel heatupValue;
    private JLabel heatupTimeValue;
    private JSlider maxFlameSize;
    private JLabel maxFlameSizeValue;
    private JSlider flameLife;
    private JLabel flameLifeValue;
    private JSlider keyStrokesPerMinute;
    private JLabel keyStrokesPerMinuteValue;
    private JCheckBox FLAMESCheckBox;
    private JCheckBox PARTICLESCheckBox;
    private JSlider sparkSize;
    private JLabel sparkSizeValue;
    private JLabel velocityFactorValue;
    private JLabel gravityFactorValue;
    private JSlider velocityFactor;
    private JSlider gravityFactor;
    private JLabel frameRateValue;
    private JSlider frameRate;
    private JSlider sparkColorRedTo;
    private JSlider sparkColorRedFrom;
    private JSlider sparkColorGreenFrom;
    private JSlider sparkColorGreenTo;
    private JSlider sparkColorBlueFrom;
    private JSlider sparkColorBlueTo;
    private JLabel sparkColorRedFromValue;
    private JLabel sparkColorRedToValue;
    private JLabel sparkColorGreenFromValue;
    private JLabel sparkColorGreenToValue;
    private JLabel sparkColorBlueFromValue;
    private JLabel sparkColorBlueToValue;
    private JLabel sparkColorAlphaValue;
    private JSlider sparkColorAlpha;
    private JPanel colorView;
    private JCheckBox visualizeEveryCaretMovementCheckBox;
    private JCheckBox PLAYMUSICCheckBox;
    private JTextField soundsFolder;
    private JCheckBox BAMCheckBox;
    private JLabel bamLifeValue;
    private JSlider bamLife;
    private JLabel heatupThresholdValue;
    private JSlider heatupThreshold;
    private JCheckBox PowerIndicatorCheckBox;
    private JTextField flameImagesFolder;
    private JTextField bamImagesFolder;
    private JCheckBox customFlameImages;
    private JCheckBox customBamImages;
    private JCheckBox HOTKEYHEATUPCheckBox;
    private JCheckBox animateBAMImagesCheckBox;
    private JLabel minVolumeValue;
    private JSlider minVolume;
    private JLabel maxVolumeValue;
    private JSlider maxVolume;


    public PowerModeConfigurableUI(PowerMode powerMode) {
        $$$setupUI$$$();
        ((MultiGradientPanel) colorView).setColorEdges(PowerMode.obtainColorEdges(powerMode));
        new ColorViewController((MultiGradientPanel) colorView, powerMode);
        powerModeEnabled.setSelected(powerMode.isEnabled());
        shakeEnabled.setSelected(powerMode.isShakeEnabled());
        shakeEnabled.addChangeListener(e -> powerMode.setShakeEnabled(shakeEnabled.isSelected()));
        FLAMESCheckBox.setSelected(powerMode.isFlamesEnabled());
        FLAMESCheckBox.addChangeListener(e -> powerMode.setFlamesEnabled(FLAMESCheckBox.isSelected()));
        PARTICLESCheckBox.setSelected(powerMode.isSparksEnabled());
        PARTICLESCheckBox.addChangeListener(e -> powerMode.setSparksEnabled(PARTICLESCheckBox.isSelected()));
        BAMCheckBox.setSelected(powerMode.isBamEnabled());
        BAMCheckBox.addChangeListener(e -> powerMode.setIsBamEnabled(BAMCheckBox.isSelected()));
        visualizeEveryCaretMovementCheckBox.setSelected(powerMode.getIsCaretAction());
        visualizeEveryCaretMovementCheckBox.addChangeListener(e -> powerMode.setIsCaretAction(visualizeEveryCaretMovementCheckBox.isSelected()));
        PLAYMUSICCheckBox.setEnabled(powerMode.mediaPlayerExists().isSuccess());
        PLAYMUSICCheckBox.setSelected(powerMode.isSoundsPlaying() && powerMode.mediaPlayerExists().isSuccess());
        PLAYMUSICCheckBox.addChangeListener(e -> powerMode.setIsSoundsPlaying(PLAYMUSICCheckBox.isSelected()));
        HOTKEYHEATUPCheckBox.setSelected(powerMode.isHotkeyHeatup());
        HOTKEYHEATUPCheckBox.addChangeListener(e -> powerMode.setHotkeyHeatup(HOTKEYHEATUPCheckBox.isSelected()));
        PowerIndicatorCheckBox.setSelected(powerMode.getIsPowerIndicatorEnabled());
        PowerIndicatorCheckBox.addChangeListener(e -> powerMode.setIsPowerIndicatorEnabled(PowerIndicatorCheckBox.isSelected()));
        animateBAMImagesCheckBox.setSelected(!powerMode.getIsSingleBamImagePerEvent());
        animateBAMImagesCheckBox.addChangeListener(e -> powerMode.setIsSingleBamImagePerEvent(!animateBAMImagesCheckBox.isSelected()));

        soundsFolder.setText(powerMode.getSoundsFolder());

        soundsFolder.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                powerMode.setSoundsFolder(soundsFolder.getText());
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                powerMode.setSoundsFolder(soundsFolder.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                powerMode.setSoundsFolder(soundsFolder.getText());
            }
        });
        initValues(powerMode.getSparkCount(), sparkCount, sparkCountValue, slider -> powerMode.setSparkCount(slider.getValue()));
        initValues(powerMode.getSparkSize(), sparkSize, sparkSizeValue, slider -> powerMode.setSparkSize(slider.getValue()));
        initValues(powerMode.getSparkLife(), sparkLife, sparkLifeValue, slider -> powerMode.setSparkLife(slider.getValue()));
        initValues(Double.valueOf((powerMode.getSparkVelocityFactor() * 100.0)).intValue(), velocityFactor, velocityFactorValue, slider -> powerMode.setSparkVelocityFactor(slider.getValue() / 100.0));
        initValues(Double.valueOf(powerMode.getGravityFactor() * 100.0).intValue(), gravityFactor, gravityFactorValue, slider -> powerMode.setGravityFactor(slider.getValue() / 100.0));
        initValues(powerMode.getShakeRange(), shakeRange, shakeRangeValue, slider -> powerMode.setShakeRange(slider.getValue()));
        initValues(powerMode.getMinVolume(), minVolume, minVolumeValue, slider -> powerMode.setMinVolume(slider.getValue()));
        initValues(powerMode.getMaxVolume(), maxVolume, maxVolumeValue, slider -> powerMode.setMaxVolume(slider.getValue()));
        bindSlieders(minVolume, maxVolume);
        initValues(powerMode.getHeatup(), heatup, heatupValue, slider -> powerMode.setHeatup(slider.getValue()));
        initValues(powerMode.getHeatupTime(), heatupTime, heatupTimeValue, slider -> powerMode.setHeatupTime(slider.getValue()));
        initValues(powerMode.getHeatupThreshold(), heatupThreshold, heatupThresholdValue, slider -> powerMode.setHeatupThreshold(slider.getValue()));
        initValues(powerMode.getFlameLife(), flameLife, flameLifeValue, slider -> powerMode.setFlameLife(slider.getValue()));
        initValues((int) powerMode.getBamLife(), bamLife, bamLifeValue, slider -> powerMode.setBamLife(slider.getValue()));
        initValues(powerMode.getmaxFlameSize(), maxFlameSize, maxFlameSizeValue, slider -> powerMode.setmaxFlameSize(slider.getValue()));
        initValues(powerMode.getKeyStrokesPerMinute(), keyStrokesPerMinute, keyStrokesPerMinuteValue, slider -> powerMode.setKeyStrokesPerMinute(slider.getValue()));
        initValues(powerMode.getFrameRateHertz(), frameRate, frameRateValue, slider -> powerMode.setFrameRateHertz(slider.getValue()));

        initValuesColor(powerMode.getRedFrom(), sparkColorRedFrom, sparkColorRedFromValue, powerMode, slider -> powerMode.setRedFrom(slider.getValue()));
        initValuesColor(powerMode.getRedTo(), sparkColorRedTo, sparkColorRedToValue, powerMode, slider -> powerMode.setRedTo(slider.getValue()));
        bindSlieders(sparkColorRedFrom, sparkColorRedTo);

        initValuesColor(powerMode.getGreenFrom(), sparkColorGreenFrom, sparkColorGreenFromValue, powerMode, slider -> powerMode.setGreenFrom(slider.getValue()));
        initValuesColor(powerMode.getGreenTo(), sparkColorGreenTo, sparkColorGreenToValue, powerMode, slider -> powerMode.setGreenTo(slider.getValue()));
        bindSlieders(sparkColorGreenFrom, sparkColorGreenTo);

        initValuesColor(powerMode.getBlueFrom(), sparkColorBlueFrom, sparkColorBlueFromValue, powerMode, slider -> powerMode.setBlueFrom(slider.getValue()));
        initValuesColor(powerMode.getBlueTo(), sparkColorBlueTo, sparkColorBlueToValue, powerMode, slider -> powerMode.setBlueTo(slider.getValue()));
        bindSlieders(sparkColorBlueFrom, sparkColorBlueTo);

        initValuesColor(powerMode.getColorAlpha(), sparkColorAlpha, sparkColorAlphaValue, powerMode, slider -> powerMode.setColorAlpha(slider.getValue()));

        customFlameImages.setSelected(powerMode.isCustomFlameImages());
        customFlameImages.addChangeListener(e -> powerMode.setCustomFlameImages(customFlameImages.isSelected()));
        {
            flameImagesFolder.setText(powerMode.getCustomFlameImageFolder());

            flameImagesFolder.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                private void setFolder(PowerMode powerMode) {
                    if (validateImagePath(powerMode,
                            PowerModeConfigurableUI.this.flameImagesFolder,
                            PowerModeConfigurableUI.this.customFlameImages)) {
                        powerMode.setCustomFlameImageFolder(flameImagesFolder.getText());
                    }
                }
            });
        }

        customBamImages.setSelected(powerMode.isCustomBamImages());
        customBamImages.addChangeListener(e -> powerMode.setCustomBamImages(customBamImages.isSelected()));

        {
            bamImagesFolder.setText(powerMode.getCustomBamImageFolder());

            bamImagesFolder.getDocument().addDocumentListener(new DocumentListener() {
                @Override
                public void insertUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    setFolder(powerMode);
                }

                private void setFolder(PowerMode powerMode) {
                    if (validateImagePath(powerMode,
                            PowerModeConfigurableUI.this.bamImagesFolder,
                            PowerModeConfigurableUI.this.customBamImages)) {
                        powerMode.setCustomBamImageFolder(bamImagesFolder.getText());
                    }
                }
            });
        }
    }

    private boolean validateImagePath(PowerMode powerMode, JTextField flameImagesFolder, JCheckBox customFlameImages) {
        String folder = flameImagesFolder.getText();
        File file = new File(folder).getAbsoluteFile();
        if (!file.exists() || file.getAbsolutePath().toLowerCase().contains("temp") || file.getAbsolutePath().toLowerCase().contains("tmp")) {
            customFlameImages.setSelected(false);
            JOptionPane.showMessageDialog(mainPanel,
                    "invalid folder! Folder '" + file.getAbsolutePath() + "' does not exist or is a temp file (contains 'Temp' or 'tmp')", "invalid folder",
                    JOptionPane.ERROR_MESSAGE);
            return false;
        } else {
            return true;
        }
    }

    private void bindSlieders(JSlider from, JSlider to) {
        from.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                if (from.getValue() > to.getValue()) {
                    to.setValue(from.getValue());
                }
            }
        });
        to.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                if (to.getValue() < from.getValue()) {
                    from.setValue(to.getValue());
                }
            }
        });
    }

    private void initValuesColor(int initValue, JSlider slider, JLabel sliderValueLabel, PowerMode powerMode, ValueColorSettable valueSettable) {
        initValues(initValue, slider, sliderValueLabel, slider1 -> {
            valueSettable.setValue(slider1);
            ((MultiGradientPanel) colorView).setColorEdges(PowerMode.obtainColorEdges(powerMode));
        });

    }

    private void initValues(int initValue, JSlider slider, JLabel sliderValueLabel, ValueSettable valueSettable) {
        slider.setValue(initValue);
        sliderValueLabel.setText(String.valueOf(initValue));
        slider.addChangeListener(new MyChangeListener(slider, sliderValueLabel) {
            @Override
            public void setValue(JSlider slider) {
                valueSettable.setValue(slider);
            }
        });
    }

    @Override
    public void reset(PowerMode powerMode) {
        powerModeEnabled.setSelected(powerMode.isEnabled());
    }

    @Override
    public boolean isModified(PowerMode powerMode) {
        return powerModeEnabled.isSelected() != powerMode.isEnabled();
    }

    @Override
    public void apply(PowerMode powerMode) throws ConfigurationException {
        powerMode.setEnabled(powerModeEnabled.isSelected());
    }


    @Override
    public JComponent getComponent() {
        return mainPanel;
    }

    private void createUIComponents() {
        colorView = new MultiGradientPanel(200, PowerMode.obtainColorEdges(PowerMode.getInstance()));


    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        mainPanel = new JPanel();
        mainPanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
        final JTabbedPane tabbedPane1 = new JTabbedPane();
        tabbedPane1.setTabLayoutPolicy(0);
        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));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
        tabbedPane1.addTab("GENERAL OPTIONS", panel1);
        final JScrollPane scrollPane1 = new JScrollPane();
        scrollPane1.setEnabled(true);
        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));
        final JPanel panel2 = new JPanel();
        panel2.setLayout(new GridLayoutManager(19, 3, new Insets(0, 0, 0, 0), -1, -1));
        scrollPane1.setViewportView(panel2);
        final JLabel label1 = new JLabel();
        label1.setText("framerate");
        label1.setToolTipText("particle & flame updates per second");
        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));
        frameRateValue = new JLabel();
        frameRateValue.setText("Label");
        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));
        frameRate = new JSlider();
        frameRate.setMaximum(120);
        frameRate.setMinimum(5);
        frameRate.setValue(30);
        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));
        powerModeEnabled = new JCheckBox();
        powerModeEnabled.setText("ENTER POWER MODE!");
        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));
        PARTICLESCheckBox = new JCheckBox();
        PARTICLESCheckBox.setText("SPARKS!");
        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));
        shakeEnabled = new JCheckBox();
        shakeEnabled.setText("SHAKE!");
        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));
        FLAMESCheckBox = new JCheckBox();
        FLAMESCheckBox.setText("FLAMES!");
        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));
        visualizeEveryCaretMovementCheckBox = new JCheckBox();
        visualizeEveryCaretMovementCheckBox.setText("VISUALIZE EVERY CARET MOVEMENT!");
        visualizeEveryCaretMovementCheckBox.setToolTipText("When disabled: only typing of letters will cause effects.\nWhen enabled: every caret movement will cause effects.");
        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));
        PLAYMUSICCheckBox = new JCheckBox();
        PLAYMUSICCheckBox.setText("PLAY MUSIC");
        PLAYMUSICCheckBox.setToolTipText("next song: shift ctrl alt M");
        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));
        soundsFolder = new JTextField();
        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));
        BAMCheckBox = new JCheckBox();
        BAMCheckBox.setText("BAM!");
        BAMCheckBox.setToolTipText("visualize document changes with BAM!");
        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));
        final JLabel label2 = new JLabel();
        label2.setText("BAM! life [ms]");
        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));
        bamLifeValue = new JLabel();
        bamLifeValue.setText("Label");
        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));
        bamLife = new JSlider();
        bamLife.setMaximum(10000);
        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));
        PowerIndicatorCheckBox = new JCheckBox();
        PowerIndicatorCheckBox.setText("POWER INDICATOR!");
        PowerIndicatorCheckBox.setToolTipText("Displays an imprecise visualization of the current heatup value.");
        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));
        final JLabel label3 = new JLabel();
        label3.setText("shake range [px]");
        label3.setToolTipText("how many pixels should the shaking move?");
        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));
        final JLabel label4 = new JLabel();
        label4.setText("min volume %");
        label4.setToolTipText("how many pixels should the shaking move?");
        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));
        final JLabel label5 = new JLabel();
        label5.setText("max volume %");
        label5.setToolTipText("how many pixels should the shaking move?");
        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));
        shakeRangeValue = new JLabel();
        shakeRangeValue.setText("Label");
        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));
        minVolumeValue = new JLabel();
        minVolumeValue.setText("Label");
        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));
        maxVolumeValue = new JLabel();
        maxVolumeValue.setText("Label");
        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));
        shakeRange = new JSlider();
        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));
        minVolume = new JSlider();
        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));
        maxVolume = new JSlider();
        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));
        final JLabel label6 = new JLabel();
        label6.setText("max flame size [px]");
        label6.setToolTipText("maximum flame size in pixels");
        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));
        maxFlameSizeValue = new JLabel();
        maxFlameSizeValue.setText("Label");
        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));
        maxFlameSize = new JSlider();
        maxFlameSize.setMaximum(500);
        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));
        final JLabel label7 = new JLabel();
        label7.setText("flame life [ms]");
        label7.setToolTipText("time to live for a flame in milliseconds");
        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));
        flameLifeValue = new JLabel();
        flameLifeValue.setText("Label");
        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));
        flameLife = new JSlider();
        flameLife.setMaximum(10000);
        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));
        final JLabel label8 = new JLabel();
        label8.setText("hint: 'heatup base level' should be <100%");
        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));
        customFlameImages = new JCheckBox();
        customFlameImages.setText("custom flame images");
        customFlameImages.setToolTipText("provide a folder with the images of a flame animation");
        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));
        flameImagesFolder = new JTextField();
        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));
        final JLabel label9 = new JLabel();
        label9.setText("image folder:");
        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));
        customBamImages = new JCheckBox();
        customBamImages.setText("custom BAM! images");
        customBamImages.setToolTipText("choose your own BAM! images");
        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));
        animateBAMImagesCheckBox = new JCheckBox();
        animateBAMImagesCheckBox.setText("animate BAM! images");
        animateBAMImagesCheckBox.setToolTipText("will cycle through all BAM! images in the given folder and create an animation (like a GIF).");
        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));
        bamImagesFolder = new JTextField();
        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));
        final JLabel label10 = new JLabel();
        label10.setText("image folder:");
        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));
        HOTKEYHEATUPCheckBox = new JCheckBox();
        HOTKEYHEATUPCheckBox.setText("HOTKEY HEATUP");
        HOTKEYHEATUPCheckBox.setToolTipText("Disable if having problems with hotkey visualization");
        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));
        final JLabel label11 = new JLabel();
        label11.setText("!!! might interfere with autocompletion and other plugins/editors!");
        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));
        final JLabel label12 = new JLabel();
        label12.setText("music folder:");
        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));
        final Spacer spacer1 = new Spacer();
        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));
        final JScrollPane scrollPane2 = new JScrollPane();
        tabbedPane1.addTab("HEATUP", scrollPane2);
        final JPanel panel3 = new JPanel();
        panel3.setLayout(new GridLayoutManager(6, 3, new Insets(0, 0, 0, 0), -1, -1));
        scrollPane2.setViewportView(panel3);
        panel3.setBorder(BorderFactory.createTitledBorder(null, "Heatup", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        final JLabel label13 = new JLabel();
        label13.setText("heatup base level [%]");
        label13.setToolTipText("the lower the level the fewer happens at the start of typing.");
        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));
        heatupValue = new JLabel();
        heatupValue.setText("Label");
        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));
        heatup = new JSlider();
        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));
        final JLabel label14 = new JLabel();
        label14.setText("heatup time [ms]");
        label14.setToolTipText("time range in milliseconds. The count of keystrokes in this period is used to calculate heatup.");
        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));
        heatupTimeValue = new JLabel();
        heatupTimeValue.setText("Label");
        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));
        heatupTime = new JSlider();
        heatupTime.setMaximum(60000);
        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));
        final JLabel label15 = new JLabel();
        label15.setText("heatup threshold [%]");
        label15.setToolTipText("how much heatup in % has to be reached until something happens");
        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));
        heatupThresholdValue = new JLabel();
        heatupThresholdValue.setText("Label");
        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));
        heatupThreshold = new JSlider();
        heatupThreshold.setMaximum(100);
        heatupThreshold.setMinimum(0);
        heatupThreshold.setValue(30);
        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));
        final JLabel label16 = new JLabel();
        label16.setText("keystrokes per minute");
        label16.setToolTipText("used to calculate heatup");
        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));
        keyStrokesPerMinuteValue = new JLabel();
        keyStrokesPerMinuteValue.setText("Label");
        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));
        keyStrokesPerMinute = new JSlider();
        keyStrokesPerMinute.setMaximum(3000);
        keyStrokesPerMinute.setValue(100);
        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));
        final JTextArea textArea1 = new JTextArea();
        textArea1.setEditable(false);
        textArea1.setEnabled(true);
        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");
        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));
        final Spacer spacer2 = new Spacer();
        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));
        final JScrollPane scrollPane3 = new JScrollPane();
        tabbedPane1.addTab("SPARKS", scrollPane3);
        final JPanel panel4 = new JPanel();
        panel4.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1));
        scrollPane3.setViewportView(panel4);
        final JPanel panel5 = new JPanel();
        panel5.setLayout(new GridLayoutManager(16, 3, new Insets(0, 0, 0, 0), -1, -1));
        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));
        panel5.setBorder(BorderFactory.createTitledBorder(null, "Sparks", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        sparkColorRedFromValue = new JLabel();
        sparkColorRedFromValue.setText("Label");
        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));
        sparkColorRedFrom = new JSlider();
        sparkColorRedFrom.setMaximum(255);
        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));
        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));
        final JLabel label17 = new JLabel();
        label17.setText("spark color red range");
        label17.setToolTipText("how many sparks should appear?");
        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));
        sparkColorRedToValue = new JLabel();
        sparkColorRedToValue.setText("Label");
        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));
        sparkColorRedTo = new JSlider();
        sparkColorRedTo.setMaximum(255);
        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));
        final JLabel label18 = new JLabel();
        label18.setText("spark color green range");
        label18.setToolTipText("how many sparks should appear?");
        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));
        sparkColorGreenFromValue = new JLabel();
        sparkColorGreenFromValue.setText("Label");
        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));
        sparkColorGreenFrom = new JSlider();
        sparkColorGreenFrom.setMaximum(255);
        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));
        sparkColorGreenToValue = new JLabel();
        sparkColorGreenToValue.setText("Label");
        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));
        sparkColorGreenTo = new JSlider();
        sparkColorGreenTo.setMaximum(255);
        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));
        final JLabel label19 = new JLabel();
        label19.setText("spark color blue range");
        label19.setToolTipText("how many sparks should appear?");
        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));
        sparkColorBlueFromValue = new JLabel();
        sparkColorBlueFromValue.setText("Label");
        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));
        sparkColorBlueFrom = new JSlider();
        sparkColorBlueFrom.setMaximum(255);
        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));
        sparkColorBlueToValue = new JLabel();
        sparkColorBlueToValue.setText("Label");
        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));
        sparkColorBlueTo = new JSlider();
        sparkColorBlueTo.setMaximum(255);
        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));
        final JLabel label20 = new JLabel();
        label20.setText("alpha");
        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));
        sparkColorAlphaValue = new JLabel();
        sparkColorAlphaValue.setText("Label");
        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));
        sparkColorAlpha = new JSlider();
        sparkColorAlpha.setMaximum(255);
        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));
        final JLabel label21 = new JLabel();
        label21.setText("spark count");
        label21.setToolTipText("how many sparks should appear?");
        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));
        sparkCountValue = new JLabel();
        sparkCountValue.setText("Label");
        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));
        sparkCount = new JSlider();
        sparkCount.setMaximum(100);
        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));
        final JLabel label22 = new JLabel();
        label22.setText("spark life [ms]");
        label22.setToolTipText("how many milliseconds should a spark live?");
        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));
        sparkLifeValue = new JLabel();
        sparkLifeValue.setText("Label");
        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));
        sparkLife = new JSlider();
        sparkLife.setMaximum(10000);
        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));
        final JLabel label23 = new JLabel();
        label23.setText("spark size [px]");
        label23.setToolTipText("spark size in pixels");
        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));
        sparkSizeValue = new JLabel();
        sparkSizeValue.setText("Label");
        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));
        sparkSize = new JSlider();
        sparkSize.setMaximum(10);
        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));
        final JLabel label24 = new JLabel();
        label24.setText("spark velocity factor %");
        label24.setToolTipText("100% is default spark velocity");
        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));
        velocityFactorValue = new JLabel();
        velocityFactorValue.setText("Label");
        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));
        velocityFactor = new JSlider();
        velocityFactor.setMaximum(10000);
        velocityFactor.setMinimum(-10000);
        velocityFactor.setValue(100);
        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));
        final JLabel label25 = new JLabel();
        label25.setText("spark gravity factor %");
        label25.setToolTipText("100% is default spark gravity");
        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));
        gravityFactorValue = new JLabel();
        gravityFactorValue.setText("Label");
        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));
        gravityFactor = new JSlider();
        gravityFactor.setMaximum(10000);
        gravityFactor.setMinimum(-10000);
        gravityFactor.setValue(100);
        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));
        final Spacer spacer3 = new Spacer();
        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));
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return mainPanel;
    }

    private interface ValueColorSettable {
        void setValue(JSlider slider);
    }

    private abstract class MyChangeListener implements ChangeListener, ValueSettable {
        private final JSlider slider;
        private final JLabel jLabel;

        public MyChangeListener(JSlider slider, JLabel jLabel) {
            this.slider = slider;
            this.jLabel = jLabel;
        }

        @Override
        public void stateChanged(ChangeEvent e) {
            setValue(slider);
            jLabel.setText(String.valueOf(slider.getValue()));
        }

    }
}


================================================
FILE: src/main/java/de/ax/powermode/power/ui/ValueSettable.java
================================================
package de.ax.powermode.power.ui;

import javax.swing.*;

/**
 * Created by nyxos on 11.03.16.
 */
public interface ValueSettable {
    void setValue(JSlider slider);
}


================================================
FILE: src/main/java/javazoom/jl/player/HackyJavaSoundAudioDevice.java
================================================
/*
 * 11/26/04		Buffer size modified to support JRE 1.5 optimizations.
 *              (CPU usage < 1% under P4/2Ghz, RAM < 12MB).
 *              jlayer@javazoom.net
 * 11/19/04		1.0 moved to LGPL.
 * 06/04/01		Too fast playback fixed. mdm@techie.com
 * 29/01/00		Initial version. mdm@techie.com
 *-----------------------------------------------------------------------
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as published
 *   by the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *----------------------------------------------------------------------
 */

package javazoom.jl.player;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;

import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.JavaLayerException;

/**
 * The <code>JavaSoundAudioDevice</code> implements an audio
 * device by using the JavaSound API.
 *
 * @author Mat McGowan
 * @since 0.0.8
 */
public class HackyJavaSoundAudioDevice extends AudioDeviceBase {
    public SourceDataLine source = null;

    public AudioFormat fmt = null;

    public byte[] byteBuf = new byte[4096];

    protected void setAudioFormat(AudioFormat fmt0) {
        fmt = fmt0;
    }

    protected AudioFormat getAudioFormat() {
        if (fmt == null) {
            Decoder decoder = getDecoder();
            fmt = new AudioFormat(decoder.getOutputFrequency(),
                    16,
                    decoder.getOutputChannels(),
                    true,
                    false);
        }
        return fmt;
    }

    protected DataLine.Info getSourceLineInfo() {
        AudioFormat fmt = getAudioFormat();
        //DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt, 4000);
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
        return info;
    }

    public void open(AudioFormat fmt) throws JavaLayerException {
        if (!isOpen()) {
            setAudioFormat(fmt);
            openImpl();
            setOpen(true);
        }
    }

    protected void openImpl()
            throws JavaLayerException {
    }


    // createSource fix.
    protected void createSource() throws JavaLayerException {
        Throwable t = null;
        try {
            Line line = AudioSystem.getLine(getSourceLineInfo());
            if (line instanceof SourceDataLine) {
                source = (SourceDataLine) line;
                //source.open(fmt, millisecondsToBytes(fmt, 2000));
                source.open(fmt);
                /*
                if (source.isControlSupported(FloatControl.Type.MASTER_GAIN))
                {
					FloatControl c = (FloatControl)source.getControl(FloatControl.Type.MASTER_GAIN);
                    c.setValue(c.getMaximum());
                }*/
                source.start();

            }
        } catch (RuntimeException ex) {
            t = ex;
        } catch (LinkageError ex) {
            t = ex;
        } catch (LineUnavailableException ex) {
            t = ex;
        }
        if (source == null) throw new JavaLayerException("cannot obtain source audio line", t);
    }

    public int millisecondsToBytes(AudioFormat fmt, int time) {
        return (int) (time * (fmt.getSampleRate() * fmt.getChannels() * fmt.getSampleSizeInBits()) / 8000.0);
    }

    protected void closeImpl() {
        if (source != null) {
            source.close();
        }
    }

    protected void writeImpl(short[] samples, int offs, int len)
            throws JavaLayerException {
        if (source == null)
            createSource();

        byte[] b = toByteArray(samples, offs, len);
        source.write(b, 0, len * 2);
    }

    protected byte[] getByteArray(int length) {
        if (byteBuf.length < length) {
            byteBuf = new byte[length + 1024];
        }
        return byteBuf;
    }

    protected byte[] toByteArray(short[] samples, int offs, int len) {
        byte[] b = getByteArray(len * 2);
        int idx = 0;
        short s;
        while (len-- > 0) {
            s = samples[offs++];
            b[idx++] = (byte) s;
            b[idx++] = (byte) (s >>> 8);
        }
        return b;
    }

    protected void flushImpl() {
        if (source != null) {
            source.drain();
        }
    }

    public int getPosition() {
        int pos = 0;
        if (source != null) {
            pos = (int) (source.getMicrosecondPosition() / 1000);
        }
        return pos;
    }

    /**
     * Runs a short test by playing a short silent sound.
     */
    public void test()
            throws JavaLayerException {
        try {
            open(new AudioFormat(22050, 16, 1, true, false));
            short[] data = new short[22050 / 10];
            write(data, 0, data.length);
            flush();
            close();
        } catch (RuntimeException ex) {
            throw new JavaLayerException("Device test failed: " + ex);
        }

    }
}


================================================
FILE: src/main/scala/de/ax/powermode/ImageUtil.scala
================================================
package de.ax.powermode

import com.intellij.util.PathUtil
import de.ax.powermode.cache.Cache
import de.ax.powermode.power.element.PowerFlame

import java.awt.image.BufferedImage
import java.io.{BufferedOutputStream, File, FileOutputStream, InputStream}
import java.net.{URI, URL}
import javax.imageio.{IIOException, ImageIO}
import scala.util.{Failure, Success, Try}

object ImageUtil {
  def imagesForPath(folder: Option[File]): scala.List[BufferedImage] = {
    val orElse = folder.getOrElse(new File("UNDEFINED"))
    //logger.debug(s"imagesForPath $folder")
    ImageUtil.listCache
      .getOrUpdate(orElse) {
        Some(folder.map(ImageUtil.images).toList.flatten.map(f => f()))
      }
      .toList
      .flatten
  }

  val imageCache =
    new Cache[URI, BufferedImage, Long](fname => new File(fname).lastModified(),
                                        fname => !new File(fname).exists())

  var lastUpdate = System.currentTimeMillis()

  val listCache = new Cache[File, List[BufferedImage], File](
    f => f,
    f =>
      if (System.currentTimeMillis() - 5000 > lastUpdate) {
        lastUpdate = System.currentTimeMillis()
        true
      } else false)

  def images(imagesPath: File): List[() => BufferedImage] = {
    val imageUrls = getImageUrls(imagesPath)
    getImagesCached(imageUrls).map(img => { () =>
      ImageUtil.deepCopy(img)
    })
  }

  import java.awt.image.BufferedImage

  def deepCopy(bi: BufferedImage): BufferedImage = {
    val cm = bi.getColorModel
    val isAlphaPremultiplied = cm.isAlphaPremultiplied
    val raster = bi.copyData(null)
    new BufferedImage(cm, raster, isAlphaPremultiplied, null)
  }

  def getUrl(uri: URI): Try[URL] = Try {
    uri.toURL
  }

  private def getImagesCached(imageUrls: List[URI]) = {
    imageUrls.flatMap(uri =>
      imageCache.getOrUpdate(uri) {
        val maybeImg = Try {
          Option(ImageIO.read(uri.toURL))
        }

        maybeImg match {
          case Success(Some(img)) =>
            val bufferedImage = new BufferedImage(img.getWidth,
                                                  img.getHeight,
                                                  BufferedImage.TYPE_INT_ARGB)
            val graphics = bufferedImage.getGraphics
            graphics.drawImage(img, 0, 0, null)
            Some(bufferedImage)
          case Failure(e) =>
            e match {
              case io: IIOException =>
                PowerMode.logger
                  .info(
                    s"could not load image file! Please try to store your PowerMode " +
                      s"Images/Animations in a different folder and restart the application! File not found: '$uri'!",
                    e
                  )
              case ex =>
                PowerMode.logger
                  .info(
                    s"could not load image file! Please try to store your PowerMode " +
                      s"Images/Animations in a different folder and restart the application! File not found: '$uri'!",
                    ex
                  )
            }
            None
          case Success(None) =>
            PowerMode.logger
              .info(s"could not load image from url '${uri.toURL}'")
            None
        }
    })
  }

  private def getImageUrls(imagesPath: File): List[URI] = {
    try {
      //logger.debug(s"FILE: $imagesPath")
      val urls = if (imagesPath.exists()) {
        getFileImages(imagesPath)
      } else if (debugFolderExists(imagesPath)) {
        getImageUrlsFromDebugDir(imagesPath)
      } else {
        getImageUrlsFromResources(imagesPath)
      }
      //logger.debug(s"URLS: $urls")
      urls
    } catch {
      case e: Throwable =>
        PowerMode.logger.debug(
          s"info getting image urls from '${imagesPath}': ${e.getMessage}",
          e)
        throw e
    }
  }

  private def getFileImages(imagesPath: File): List[URI] = {
    //logger.debug(s"LOADING FROM normal path: $imagesPath")

    val files = if (imagesPath.isFile) {
      List(imagesPath)
    } else {
      Option(imagesPath.getAbsoluteFile.listFiles())
        .map(_.toList)
        .toList
        .flatten
        .filter(_.isFile)
    }
    files.map(_.getAbsoluteFile.toURI)
  }

  private def debugFolderExists(imagesPath: File): Boolean = {
    val file = new File(PathUtil.getJarPathForClass(classOf[PowerFlame]),
                        imagesPath.getPath)
    file.exists()
  }

  private def getImageUrlsFromDebugDir(imagesPath: File): List[URI] = {
    val file = new File(PathUtil.getJarPathForClass(classOf[PowerFlame]),
                        imagesPath.getPath)
    //logger.debug(s"LOADING FROM exploded sandbox: $file")
    Option(file.listFiles())
      .map(_.toList)
      .toList
      .flatten
      .filter(_.isFile)
      .map(_.toURI)
  }

  def writeBytes(data: LazyList[Byte], file: File) = {
    val target = new BufferedOutputStream(new FileOutputStream(file))
    try data.foreach(target.write(_))
    finally target.close()
  }

  lazy val fireUrls = (1 to 25)
    .map(i => if (i > 9) s"$i" else s"0$i")
    .map { i =>
      mkTmpImg(
        classOf[PowerFlame].getResourceAsStream(
          s"/fire/animated/256/fire1_ $i.png"))
    }
    .toList

  lazy val bamUrls =
    Option(classOf[PowerFlame].getResourceAsStream(s"/bam/bam.png"))
      .map(mkTmpImg)
      .toList

  private def getImageUrlsFromResources(imagesFolder: File): List[URI] = {
    val loader = this.getClass().getClassLoader()
    //logger.debug(s"LOADING FROM JAR: $imagesFolder")
    val uRLs: List[URL] = if (imagesFolder.getPath.contains("fire")) {
      fireUrls
    } else if (imagesFolder.getPath.contains("bam")) {
      bamUrls
    } else {
      None.toList
    }
    uRLs.map(_.toURI)
  }

  private def mkTmpImg(stream: InputStream): URL = {
    import java.io.File
    val tempFile =
      File.createTempFile(s"${System.currentTimeMillis()}_pmtempfile_", ".png")
    tempFile.deleteOnExit()
    writeBytes(
      LazyList.continually(stream.read).takeWhile(_ != -1).map(_.toByte),
      tempFile)
    tempFile.toURI.toURL
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/MyCaretListener.scala
================================================
package de.ax.powermode

import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.event.{CaretEvent, CaretListener}

import java.util.concurrent.atomic.AtomicInteger
import java.util.function.IntUnaryOperator
import scala.util.Try

/**
  * Created by nyxos on 04.01.17.
  */
class MyCaretListener extends CaretListener with Power {
  var modified = true

  val caretCount = new AtomicInteger(1)
  override def caretPositionChanged(caretEvent: CaretEvent): Unit = {
    if (!modified && powerMode.caretAction) {
      initializeAnimationByCaretEvent(caretEvent.getCaret)
    }
    modified = false
  }

  override def caretRemoved(caretEvent: CaretEvent): Unit = {
    modified = true
    caretCount.getAndUpdate((i: Int) => {
      if (i > 2) {
        i - 1
      } else {
        1
      }
    })
  }

  override def caretAdded(caretEvent: CaretEvent): Unit = {
    modified = true
    caretCount.getAndIncrement()
  }

  private def initializeAnimationByCaretEvent(caret: Caret): Unit = {
    val isActualEditor = Try {
      Util.isActualEditor(caret.getEditor)
    }.getOrElse(false)
    if (isActualEditor) {
      Util
        .getCaretPosition(caret)
        .toOption
        .foreach(p =>
          powerMode.maybeElementOfPowerContainerManager.foreach(
            _.initializeAnimation(caret.getEditor, p)))
    }
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/MyTypedActionHandler.scala
================================================
package de.ax.powermode

import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.actionSystem.TypedActionHandler

import java.awt.Point
import scala.jdk.CollectionConverters._

/**
  * Created by nyxos on 04.01.17.
  */
class MyTypedActionHandler(typedActionHandler: TypedActionHandler)
    extends TypedActionHandler
    with Power {

  def execute(editor: Editor, c: Char, dataContext: DataContext): Unit = {
    if (powerMode.isEnabled) {
      powerMode.increaseHeatup(dataContext = Option(dataContext))
      if (!powerMode.caretAction) {
        initializeAnimationByTypedAction(editor)
      }
    }
    try {
      typedActionHandler.execute(editor, c, dataContext)
    } catch {
      case x: IllegalStateException =>
        logger.debug(x.getMessage, x)
      case x: IndexOutOfBoundsException =>
        logger.debug(x.getMessage, x)
    }
  }

  def getEditorCaretPositions(editor: Editor): Seq[Point] = {
    editor.getCaretModel.getAllCarets.asScala.toList
      .map({ c =>
        Util.getCaretPosition(editor, c)
      })
      .filter(_.isSuccess)
      .map(_.get)
  }

  def initializeAnimationByTypedAction(editor: Editor): Unit = {

    val isActualEditor = Util.isActualEditor(editor)
    if (isActualEditor) {
      val positions = getEditorCaretPositions(editor)
      positions.foreach(pos => {
        powerMode.maybeElementOfPowerContainerManager.foreach(
          _.initializeAnimation(editor, pos))
      })
    }
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/NextSongAction.scala
================================================
package de.ax.powermode

import com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}

/**
  * Created by nyxos on 27.12.16.
  */
class NextSongAction extends AnAction with Power {
  override def actionPerformed(anActionEvent: AnActionEvent): Unit = {
    powerMode.maybeElementOfPowerContainerManager.foreach(cm => {
      cm.sound.foreach(_.next())
    })
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/Power.scala
================================================
package de.ax.powermode

/**
  * Created by nyxos on 04.01.17.
  */
trait Power {
  def powerMode: PowerMode = {
    PowerMode.getInstance
  }

  def logger = PowerMode.logger
}


================================================
FILE: src/main/scala/de/ax/powermode/PowerMode.scala
================================================
/*
 * Copyright 2015 Baptiste Mesta
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.ax.powermode

import com.intellij.openapi.Disposable
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.{
  ApplicationComponent,
  PersistentStateComponent,
  Service,
  State,
  Storage
}
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.actionSystem.{
  EditorActionManager,
  TypedAction
}
import com.intellij.util.xmlb.XmlSerializerUtil
import de.ax.powermode.PowerMode.logger
import de.ax.powermode.power.color.ColorEdges
import de.ax.powermode.power.management.ElementOfPowerContainerManager
import org.apache.commons.math3.stat.regression.SimpleRegression
import com.intellij.openapi.diagnostic.Logger
import de.ax.powermode.power.hotkeys.HotkeyHeatupListener
import org.jetbrains.annotations.Nullable
import squants.Dimensionless
import squants.DimensionlessConversions.{DimensionlessConversions, each}
import squants.time.Time._
import squants.time.Frequency._
import squants.time.TimeConversions._
import squants.time.FrequencyConversions._
import squants.MetricSystem._
import squants.time.{Frequency, Time, TimeUnit}

import scala.language.postfixOps
import java.awt.event.InputEvent
import java.io.File
import javax.swing.KeyStroke
import scala.collection.immutable.Seq
import scala.util.Try

/**
  * @author Baptiste Mesta
  */
object PowerMode {

  val logger: Logger = Logger.getInstance(classOf[PowerMode])
  private var instance: PowerMode = null
  @Nullable def getInstance: PowerMode = synchronized {
    if (instance != null) {
      instance
    } else {
      logger.debug("No instance!")
      try {
        instance =
          ApplicationManager.getApplication.getService(classOf[PowerMode])
        instance.initComponent()
        instance
      } catch {
        case e: Throwable =>
          logger.debug("info getting component: " + e.getMessage(), e)
          null
      }
    }
  }

  def obtainColorEdges(pm: PowerMode): ColorEdges = {
    import pm._
    val edges = new ColorEdges()
    edges.setAlpha(getColorAlpha)
    edges.setRedFrom(getRedFrom)
    edges.setRedTo(getRedTo)
    edges.setGreenFrom(getGreenFrom)
    edges.setGreenTo(getGreenTo)
    edges.setBlueFrom(getBlueFrom)
    edges.setBlueTo(getBlueTo)
    edges
  }
}

//@Service(Array(Service.Level.APP))
@State(name = "PowerModeII",
       storages = Array(new Storage(file = "$APP_CONFIG$/power.mode.ii.xml")))
final class PowerMode
    extends PersistentStateComponent[PowerMode]
    with Disposable {

  override def dispose(): Unit = {
    maybeElementOfPowerContainerManager.foreach(_.dispose)
  }

  type Timestamp = Time
  type CaretCount = Int
  type HeatupKey = (Option[KeyStroke], Timestamp, CaretCount)
  val mediaPlayerExists: Try[Class[_]] = Try {
    Class.forName("javax.sound.sampled.SourceDataLine")
  }
  var isSingleBamImagePerEvent: Boolean = false
  var hotkeyHeatup: Boolean = true
  var bamLife: Time = 1000 milliseconds
  var soundsFolder = Option.empty[File]
  var minVolume: Dimensionless = 10.percent
  var maxVolume: Dimensionless = 100.percent

  def getMinVolume: Int = minVolume.toPercent.toInt

  def setMinVolume(value: Int): Unit = {
    minVolume = value.percent
    logger.debug(s"Setting min volume ${minVolume}")
    maxVolume = Seq(minVolume, maxVolume).max
  }

  def getMaxVolume: Int = maxVolume.toPercent.toInt

  def setMaxVolume(value: Int): Unit = {
    maxVolume = value.percent
    logger.debug(s"Setting max volume ${maxVolume}")
    minVolume = Seq(minVolume, maxVolume).min
  }

  var gravityFactor: Double = 21.21
  var sparkVelocityFactor: Double = 4.36
  var sparkSize = 3
  var sparksEnabled = true
  var frameRate: Frequency = 30 hertz
  var maxFlameSize: Int = 100
  var maxFlameLife: Time = 2000 milliseconds
  var heatupTimeMillis: Time = 10000 milliseconds
  var lastKeys = List.empty[HeatupKey]
  var keyStrokesPerMinute: Frequency = 300 / 1.minutes
  var heatupFactor = 1.0
  var sparkLife = 3000
  var sparkCount = 10
  var shakeRange: Int = 4
  var flamesEnabled: Boolean = true
  var maybeElementOfPowerContainerManager
    : Option[ElementOfPowerContainerManager] =
    Option.empty
  var isBamEnabled: Boolean = true
  var isSoundsPlaying: Boolean = false
  var powerIndicatorEnabled: Boolean = true
  var caretAction: Boolean = false
  var hotkeyWeight: Dimensionless = keyStrokesPerMinute * (3 seconds)
  var redFrom: Int = 0
  var redTo: Int = 255
  var greenFrom: Int = 0
  var greenTo: Int = 255
  var blueFrom: Int = 0
  var blueTo: Int = 255
  var colorAlpha: Int = 164
  var heatupThreshold: Double = 0.0
  var _isCustomFlameImages: Boolean = false
  var _isCustomBamImages: Boolean = false
  var customFlameImageFolder = Option.empty[File]
  var customBamImageFolder = Option.empty[File]
  private var enabled: Boolean = true
  private var shakeEnabled: Boolean = false

  def isHotkeyHeatup: Boolean = hotkeyHeatup

  def setHotkeyHeatup(h: Boolean): Unit = {
    hotkeyHeatup = h
  }

  def flameImageFolder: Option[File] = {
    if (!_isCustomFlameImages) Some(new File("fire/animated/256"))
    else customFlameImageFolder
  }

  def bamImageFolder: Option[File] = {
    if (!_isCustomBamImages) Some(new File("bam")) else customBamImageFolder
  }

  def getFrameRateHertz(): Int = frameRate.toHertz.toInt

  def setFrameRateHertz(f: Int): Unit = {
    frameRate = f hertz
  }

  def increaseHeatup(
      dataContext: Option[DataContext] = Option.empty[DataContext],
      keyStroke: Option[KeyStroke] = Option.empty[KeyStroke]): Unit = {

    val currentTime = System.currentTimeMillis().milliseconds
    lastKeys = (keyStroke, currentTime, myCaretListener.caretCount.get()) :: filterLastKeys(
      currentTime)
    dataContext.foreach(dc =>
      maybeElementOfPowerContainerManager.foreach(_.showIndicator(dc)))

  }

  var previousValues = List.empty[Double]

  def reduceHeatup: Unit = {
    val ct = System.currentTimeMillis().milliseconds
    lastKeys = filterLastKeys(ct)
    adjustValueFactor
  }

  private def adjustValueFactor: Unit = {
    if (previousValues.size > frameRate.toHertz) {
      previousValues = previousValues.dropRight(1)
    }
    val unlimited = rawValueFactorUnlimited
    val wouldValues = unlimited :: previousValues
    val slope = if (wouldValues.size > 1) {
      val s = new SimpleRegression()
      wouldValues.zipWithIndex.foreach {
        case (e, i) =>
          s.addData(i, e)
      }
      s.getSlope
    } else {
      0
    }
    val maxSlope = 0.001
    val maxSlopeValue = 0.0005
    if (slope > maxSlope) {
      rvf *= (1.0 + maxSlopeValue)
    } else if (slope < -maxSlope) {
      rvf *= (1.0 - maxSlopeValue)
    } else {
      rvf = unlimited
    }
    previousValues ::= rvf
  }

  private def filterLastKeys(currentTime: Time): List[HeatupKey] = {
    lastKeys.filter(_._2 >= currentTime - heatupTimeMillis)
  }
  var rvf: Double = 0.0
  def rawValueFactor: Double = { rvf }
  def rawValueFactorUnlimited: Double = {
    val base = heatupFactor +
      ((1 - heatupFactor) * rawTimeFactorFromKeyStrokes)
    (base - heatupThreshold) / (1 - heatupThreshold)
  }

  def rawTimeFactorFromKeyStrokes: Double = {
    val tf = Try {
      if (heatupTimeMillis < 1.seconds) {
        1 ea
      } else {
        val MaxKeystrokesOverHeatupTime
          : Dimensionless = heatupTimeMillis * keyStrokesPerMinute
        val vals: Seq[Dimensionless] = lastKeys.map {
          case (Some(ks), _, caretCount) =>
            val size = Seq(InputEvent.CTRL_DOWN_MASK,
                           InputEvent.ALT_DOWN_MASK,
                           InputEvent.SHIFT_DOWN_MASK)
              .count(m => (ks.getModifiers & m) > 0)
            (size * hotkeyWeight * caretCount)
          case (_, _, caretCount) => 1.ea * caretCount
        }

        val keystrokesOverHeatupTime: Dimensionless = vals.foldLeft(0.ea)(_ + _)
        val res = (keystrokesOverHeatupTime / MaxKeystrokesOverHeatupTime).ea
        res
      }
    }.getOrElse(0 ea)
    tf.toEach
  }

  def valueFactor: Dimensionless = {
    math.min(math.max(rawValueFactor, 0), 1) * 100.percent
  }

  def timeFactor: Dimensionless = {
    math.min(math.max(rawTimeFactorFromKeyStrokes, 0), 1) * 100.percent
  }
  val myCaretListener = new MyCaretListener()
  // NOTE: this is called in the constructor, at the very end of this file 👇
  def initComponent(): Unit = {
    PowerMode.logger.debug(s"initComponent... ${System.out.hashCode()}",
                           new Exception("let's trace the origin"))
    logger.debug("initComponentPrinted...")
    val editorFactory = EditorFactory.getInstance
    maybeElementOfPowerContainerManager = Some(
      new ElementOfPowerContainerManager)
    maybeElementOfPowerContainerManager.foreach(
      editorFactory.addEditorFactoryListener(_, this))

    EditorFactory
      .getInstance()
      .getEventMulticaster
      .addCaretListener(myCaretListener, this)
    maybeElementOfPowerContainerManager.map(cm => {
      val typedAction = TypedAction
        .getInstance()
      typedAction
        .setupRawHandler(new MyTypedActionHandler(typedAction.getRawHandler))
    })
    val l = new HotkeyHeatupListener
    PowerMode.logger.debug("initComponent done")
  }

  override def getState: PowerMode = {
    this
  }

  override def loadState(state: PowerMode): Unit = {
    XmlSerializerUtil.copyBean(state, this)
  }

  def isEnabled: Boolean = {
    enabled
  }

  def setEnabled(enabled: Boolean): Unit = {
    this.enabled = enabled
  }

  def isShakeEnabled: Boolean = {
    shakeEnabled
  }

  def setShakeEnabled(shakeEnabled: Boolean): Unit = {
    this.shakeEnabled = shakeEnabled
  }

  def getSparkCount: Int = sparkCount

  def setSparkCount(sparkCount: Int): Unit = {
    this.sparkCount = sparkCount
  }

  def getSparkLife: Int = sparkLife

  def setSparkLife(sparkRange: Int): Unit = {
    this.sparkLife = sparkRange
  }

  def getShakeRange: Int = shakeRange

  def setShakeRange(shakeRange: Int): Unit = {
    this.shakeRange = shakeRange
  }

  def getHeatup: Int = (heatupFactor * 100).toInt

  def setHeatup(heatup: Int): Unit = {
    this.heatupFactor = heatup / 100.0
  }

  def getHeatupTime: Int = heatupTimeMillis.toMilliseconds.toInt

  def setHeatupTime(heatupTime: Int): Unit = {
    this.heatupTimeMillis = math.max(0, heatupTime) milliseconds
  }

  def getFlameLife: Int = {
    maxFlameLife.toMilliseconds.toInt
  }

  def setFlameLife(flameLife: Int): Unit = {
    maxFlameLife = flameLife.milliseconds
  }

  def getmaxFlameSize: Int = {
    maxFlameSize
  }

  def setmaxFlameSize(maxFlameSize: Int): Unit = {
    this.maxFlameSize = maxFlameSize
  }

  def getKeyStrokesPerMinute: Int = {
    (keyStrokesPerMinute * 1.minutes).toEach.toInt
  }

  def setKeyStrokesPerMinute(keyStrokesPerMinute: Int): Unit = {
    this.keyStrokesPerMinute = keyStrokesPerMinute / 1.minutes
  }

  def isFlamesEnabled: Boolean = {
    flamesEnabled
  }

  def setFlamesEnabled(flamesEnabled: Boolean): Unit = {
    this.flamesEnabled = flamesEnabled
  }

  def isSparksEnabled: Boolean = {
    sparksEnabled
  }

  def setSparksEnabled(sparksEnabled: Boolean): Unit = {
    this.sparksEnabled = sparksEnabled
  }

  def getSparkSize: Int = {
    sparkSize
  }

  def setSparkSize(sparkSize: Int): Unit = {
    this.sparkSize = sparkSize
  }

  def getGravityFactor(): Double = gravityFactor

  def setGravityFactor(f: Double): Unit = {
    gravityFactor = f
  }

  def getSparkVelocityFactor(): Double = sparkVelocityFactor

  def setSparkVelocityFactor(f: Double): Unit = {
    sparkVelocityFactor = f
  }

  def getRedFrom: Int = {
    redFrom
  }

  def setRedFrom(redFrom: Int): Unit = {
    if (redFrom <= redTo)
      this.redFrom = redFrom
  }

  def getRedTo: Int = {
    redTo
  }

  def setRedTo(redTo: Int): Unit = {
    if (redTo >= redFrom)
      this.redTo = redTo
  }

  def getGreenTo: Int = {
    greenTo
  }

  def setGreenTo(greenTo: Int): Unit = {
    if (greenTo >= greenFrom)
      this.greenTo = greenTo
  }

  def getGreenFrom: Int = {
    greenFrom
  }

  def setGreenFrom(gf: Int): Unit = {
    if (gf <= greenTo)
      greenFrom = gf
  }

  def getBlueTo: Int = {
    blueTo
  }

  def setBlueTo(blueTo: Int): Unit = {
    if (blueTo >= getBlueFrom)
      this.blueTo = blueTo
  }

  def getBlueFrom: Int = {
    blueFrom
  }

  def setBlueFrom(bf: Int): Unit = {
    if (bf <= blueTo)
      blueFrom = bf
  }

  def getColorAlpha: Int = {
    colorAlpha
  }

  def setColorAlpha(alpha: Int): Unit = {
    colorAlpha = alpha
  }

  def getSoundsFolder: String =
    soundsFolder.map(_.getAbsolutePath).getOrElse("")

  def setSoundsFolder(file: String): Unit = {
    soundsFolder = Option(new File(file))
  }

  def getIsCaretAction: Boolean = {
    caretAction
  }

  def setIsCaretAction(isCaretAction: Boolean): Unit = {
    this.caretAction = isCaretAction
  }

  def getIsSoundsPlaying: Boolean = isSoundsPlaying

  def setIsSoundsPlaying(isSoundsPlaying: Boolean): Unit = {
    this.isSoundsPlaying = isSoundsPlaying
  }

  def getBamLife: Double = bamLife.toMilliseconds

  def setBamLife(l: Long): Unit = {
    bamLife = l.milliseconds
  }

  def getIsBamEnabled: Boolean = isBamEnabled

  def setIsBamEnabled(b: Boolean): Unit = {
    isBamEnabled = b
  }

  def getHeatupThreshold: Int = {
    (heatupThreshold * 100.0).toInt
  }

  def setHeatupThreshold(t: Int): Unit = {
    heatupThreshold = t / 100.0
  }

  def getIsPowerIndicatorEnabled: Boolean = {
    powerIndicatorEnabled
  }

  def setIsPowerIndicatorEnabled(enabled: Boolean): Unit = {
    powerIndicatorEnabled = enabled
  }

  def isCustomFlameImages: Boolean = _isCustomFlameImages

  def setCustomFlameImages(s: Boolean): Unit = {
    _isCustomFlameImages = s
  }

  def isCustomBamImages: Boolean = _isCustomBamImages

  def setCustomBamImages(s: Boolean): Unit = {
    _isCustomBamImages = s
  }

  def getCustomFlameImageFolder: String =
    customFlameImageFolder.map(_.getAbsolutePath).getOrElse("")

  def setCustomFlameImageFolder(file: String): Unit = {
    customFlameImageFolder = Option(new File(file))
  }

  def getCustomBamImageFolder: String =
    customBamImageFolder.map(_.getAbsolutePath).getOrElse("")

  def setCustomBamImageFolder(file: String): Unit = {
    customBamImageFolder = Option(new File(file))
  }

  def getIsSingleBamImagePerEvent(): Boolean = {
    isSingleBamImagePerEvent
  }

  def setIsSingleBamImagePerEvent(isSingleBamImagePerEvent: Boolean): Unit = {
    this.isSingleBamImagePerEvent = isSingleBamImagePerEvent
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/PowerModeConfigurable.scala
================================================
/*
 * Copyright 2015 Baptiste Mesta
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.ax.powermode

import com.intellij.openapi.options.ConfigurableBase
import de.ax.powermode.power.ui.PowerModeConfigurableUI

/**
  * @author Baptiste Mesta
  */
class PowerModeConfigurable()
    extends ConfigurableBase[PowerModeConfigurableUI, PowerMode](
      "power.mode.II",
      "Power Mode II",
      "power.mode.II") {
  val settings: PowerMode = PowerMode.getInstance

  protected def getSettings: PowerMode = {
    if (settings == null) {
      throw new IllegalStateException("power mode is null")
    }
    settings
  }

  protected def createUi: PowerModeConfigurableUI = {
    new PowerModeConfigurableUI(settings)
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/PowerModeStartup.scala
================================================
package de.ax.powermode

import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity

import java.util
object PowerModeStartup {
  def start(): Unit = synchronized {
    PowerMode.logger.debug(s"starting instance on out ${System.out.hashCode()}")
    val x = PowerMode.getInstance
    PowerMode.logger.debug(s"started instance ${x.hashCode()}")
  }
}
class PowerModeStartup extends com.intellij.ide.AppLifecycleListener {
  override def appFrameCreated(commandLineArgs: util.List[String]): Unit = {
    PowerModeStartup.start()
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/TogglePowerMode.scala
================================================
package de.ax.powermode

import com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}

/**
  * Created by nyxos on 31.03.16.
  */
class TogglePowerMode extends AnAction with Power {
  def actionPerformed(e: AnActionEvent): Unit = {
    powerMode.setEnabled(!powerMode.isEnabled)
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/Util.scala
================================================
package de.ax.powermode

import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.editor.{Caret, Editor, EditorKind, VisualPosition}

import java.awt.Point
import scala.util.Try

/**
  * Created by nyxos on 30.09.16.
  */
object Util {
  def alpha(f: Float): Float = {
    if (f < 0) {
      0f
    } else if (f > 1) {
      1f
    } else {
      f
    }
  }

  def isActualEditor(editor: Editor): Boolean = {
    println(
      s"editor.getClass: ${editor.getClass} ${editor.toString} ${editor.getEditorKind} ${editor.getDocument.isWritable}")
    editor match {
      case e if e.isViewer =>
        false
      case e if e.isOneLineMode =>
        false
      case impl: EditorImpl =>
        try {
          Set(EditorKind.MAIN_EDITOR, EditorKind.DIFF)
            .contains(impl.getEditorKind)
        } catch {
          case _: Throwable => false
        }
      case _ =>
        false
    }
  }

  def editorOk(editor: Editor, maxSize: Int): Boolean = {
    !(editor match {
      case impl: EditorImpl =>
        try {
          impl.getPreferredSize.height < maxSize || impl.getPreferredSize.width < maxSize
        } catch {
          case _: Throwable => true
        }
      case _ =>
        false
    })
  }

  def interceptError[T](f: => T): T = {
    try {
      f
    } catch {
      case e: Throwable =>
        throw e
    }
  }

  def getPoint(position: VisualPosition, editor: Editor): Point = {
    val p: Point = editor.visualPositionToXY(position)
    val location = editor.getScrollingModel.getVisibleArea.getLocation
    p.translate(-location.x, -location.y)
    p
  }

  def getCaretPosition(caret: Caret): Try[Point] = Try {
    getPoint(caret.getVisualPosition, caret.getEditor)
  }

  def getCaretPosition(editor: Editor, c: Caret): Try[Point] = Try {
    val p: Point = editor.visualPositionToXY(c.getVisualPosition)
    val location = editor.getScrollingModel.getVisibleArea.getLocation
    p.translate(-location.x, -location.y)
    p
  }

}


================================================
FILE: src/main/scala/de/ax/powermode/cache/Cache.scala
================================================
package de.ax.powermode.cache

import scala.collection.mutable;

class Cache[K, V, I](compareValue: K => I, shoudUpdate: K => Boolean) {

  val cache: mutable.HashMap[K, (V, I)] = mutable.HashMap.empty[K, (V, I)]

  def getOrUpdate(k: K)(orUpdate: => Option[V]): Option[V] = {
    var kInfo = compareValue(k)
    val maybeV1 = if (shoudUpdate(k)) {
      None
    } else {
      cache
        .get(k)
        .collect { case (v, i) => if (kInfo == i) Some(v) else None }
        .flatten
    }
    maybeV1 match {
      case Some(v) =>
        Some(v)
      case None =>
        val nvo = orUpdate
        nvo.map(nv => cache.put(k, (nv, kInfo)))
        nvo
    }
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/package.scala
================================================
/**
  * Created by nyxos on 13.03.16.
  */
package object powermode {

  type PowerColor = (Float, Float, Float, Float)
}


================================================
FILE: src/main/scala/de/ax/powermode/power/ElementOfPower.scala
================================================
package de.ax.powermode.power

import de.ax.powermode.Power

import java.awt.Graphics

/**
  * Created by nyxos on 10.03.16.
  */
trait ElementOfPower extends Power {

  def update(delta: Float): Boolean

  def render(g: Graphics, dxx: Int, dyy: Int): Unit

  def life: Long

  def initLife: Long

  def lifeFactor: Float = {
    1 - ((life - System.currentTimeMillis()) / initLife.toFloat)
  }

  def alive: Boolean = {
    life > System
      .currentTimeMillis() && powerMode.isEnabled //&& width >= 0 && width <= _width
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/power/color/ColorEdges.scala
================================================
package de.ax.powermode.power.color

import java.awt.Color

class ColorEdges(var leftTop: MyPaint = MyPaint(0, 0, 0, 255),
                 var rightTop: MyPaint = MyPaint(255, 0, 0, 255),
                 var leftBottom: MyPaint = MyPaint(0, 255, 0, 255),
                 var rightBottom: MyPaint = MyPaint(255, 255, 0, 255)) {

  implicit def mp2Color(mp: MyPaint): Color = mp.color

  def getLeftTop: Color = {
    return leftTop
  }

  def getRightTop: Color = {
    return rightTop
  }

  def getLeftBottom: Color = {
    return leftBottom
  }

  def getRightBottom: Color = {
    return rightBottom
  }

  def updateColors(c1: Int): Unit = {
    leftTop = updateMyPaint(c1, leftTop)
    rightTop = updateMyPaint(c1, rightTop)
    leftBottom = updateMyPaint(c1, leftBottom)
    rightBottom = updateMyPaint(c1, rightBottom)
  }

  private def updateMyPaint(c: Int, MyPaint: MyPaint): MyPaint = {
    return MyPaint.withBlue(c)
  }

  def setLeftTop(leftTop: MyPaint): Unit = {
    this.leftTop = leftTop
  }

  def setRightTop(rightTop: MyPaint): Unit = {
    this.rightTop = rightTop
  }

  def setLeftBottom(leftBottom: MyPaint): Unit = {
    this.leftBottom = leftBottom
  }

  def setRightBottom(rightBottom: MyPaint): Unit = {
    this.rightBottom = rightBottom
  }

  def setRedFrom(redFrom: Int): Unit = {
    this.leftTop = leftTop.withRed(redFrom)
    this.leftBottom = leftBottom.withRed(redFrom)
  }

  def setRedTo(redTo: Int): Unit = {
    this.rightTop = rightTop.withRed(redTo)
    this.rightBottom = rightBottom.withRed(redTo)
  }

  def setGreenFrom(redFrom: Int): Unit = {
    this.leftTop = leftTop.withGreen(redFrom)
    this.rightTop = rightTop.withGreen(redFrom)
  }

  def setGreenTo(redTo: Int): Unit = {
    this.leftBottom = leftBottom.withGreen(redTo)
    this.rightBottom = rightBottom.withGreen(redTo)
  }

  def setBlueFrom(redFrom: Int): Unit = {
    this.leftTop = leftTop.withBlue(redFrom)
    this.leftBottom = leftBottom.withBlue(redFrom)
  }

  def setBlueTo(redTo: Int): Unit = {
    this.rightTop = rightTop.withBlue(redTo)
    this.rightBottom = rightBottom.withBlue(redTo)
  }

  def setAlpha(alpha: Int): Unit = {
    this.leftTop = leftTop.withAlpha(alpha)
    this.leftBottom = leftBottom.withAlpha(alpha)
    this.rightTop = rightTop.withAlpha(alpha)
    this.rightBottom = rightBottom.withAlpha(alpha)
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/power/color/MyPaint.scala
================================================
package de.ax.powermode.power.color

import java.awt.Color

/**
  * Created by nyxos on 05.07.16.
  */
case class MyPaint(r: Int, g: Int, b: Int, a: Int = 255) {
  def withRed(rr: Int) = copy(r = rr)

  def withGreen(gg: Int) = copy(g = gg)

  def withBlue(bb: Int) = copy(b = bb)

  def withAlpha(aa: Int) = copy(a = aa)

  lazy val color = new Color(r, g, b, a)
}


================================================
FILE: src/main/scala/de/ax/powermode/power/element/PowerBam.scala
================================================
package de.ax.powermode.power.element

import de.ax.powermode.power.ElementOfPower
import de.ax.powermode.{ImageUtil, Util}

import java.awt.image.BufferedImage
import java.awt.{AlphaComposite, Graphics, Graphics2D}
import scala.language.postfixOps

/**
  * Created by nyxos on 28.12.16.
  */
case class PowerBam(_x: Float,
                    _y: Float,
                    var _width: Float,
                    var _height: Float,
                    initLife: Long)
    extends ElementOfPower {
  logger.debug(s"x ${_x}, y ${_y}, w ${_width}, h ${_height}")

  val life = System.currentTimeMillis() + initLife
  var x: Double = _x
  var y: Double = _y
  var width: Double = 0
  var height: Double = 0

  var i = 0

  var currentImage: Option[BufferedImage] =
    if (powerMode.isSingleBamImagePerEvent) {
      val bis = ImageUtil.imagesForPath(powerMode.bamImageFolder)
      val img = bis((math.random() * (bis.size - 1)) % bis.size toInt)
      val ih = img.getWidth / img.getHeight.toDouble
      logger.debug(s"img ${img.getWidth} / ${img.getHeight}")
      logger.debug(s"old ${_width} ${_height}")
      if (ih > 1) {
        _height = (_height / ih).toFloat
        _width = _width
      } else {
        _height = _height
        _width = (_width * ih).toFloat
      }
      logger.debug(s"new ${_width} ${_height}")
      Option(img)
    } else {
      None
    }

  override def update(delta: Float): Boolean = {
    if (alive) {
      if (!powerMode.isSingleBamImagePerEvent) {
        val bis = ImageUtil.imagesForPath(powerMode.bamImageFolder)
        if (bis.nonEmpty) {
          currentImage = Option(bis(i % bis.size))
        }
      }
      i += 1
      x = _x + (0.5 * _width) - (0.5 * _width * lifeFactor)
      y = _y + (0.5 * _height) - (0.5 * _height * lifeFactor)
      width = _width * lifeFactor
      height = _height * lifeFactor
    }
    !alive
  }

  override def render(g: Graphics, dxx: Int, dyy: Int): Unit = {
    currentImage.foreach { currentImage =>
      if (alive) {
        val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]
        g2d.setComposite(
          AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                                     Util.alpha(0.9f * (1 - lifeFactor))))
        g2d.drawImage(currentImage,
                      x + dxx toInt,
                      y + dyy toInt,
                      width toInt,
                      height toInt,
                      null)
        g2d.dispose()
      }
    }

  }
}


================================================
FILE: src/main/scala/de/ax/powermode/power/element/PowerFlame.scala
================================================
package de.ax.powermode.power.element

import de.ax.powermode.power.ElementOfPower
import de.ax.powermode.{ImageUtil, Util}

import java.awt.image.BufferedImage
import java.awt.{AlphaComposite, Graphics, Graphics2D}

case class PowerFlame(_x: Int,
                      _y: Int,
                      _width: Int,
                      _height: Int,
                      initLife: Long,
                      up: Boolean)
    extends ElementOfPower {
  val life = System.currentTimeMillis() + initLife
  var x = _x
  var y = _y
  var width = 0
  var height = 0

  var i = 0
  var currentImage: BufferedImage = null

  override def update(delta: Float): Boolean = {
    if (alive) {
      val flameImages1 = ImageUtil.imagesForPath(powerMode.flameImageFolder)
      if (flameImages1.nonEmpty) {
        currentImage = flameImages1(i % flameImages1.size)
      }
      i += 1
      x = _x - (0.5 * _width * lifeFactor).toInt
      if (up)
        y = _y - (1.1 * _height * lifeFactor).toInt
      else
        y = _y + (0.25 * _height * lifeFactor).toInt
      width = (_width * lifeFactor).toInt
      height = (_height * lifeFactor).toInt
    }
    !alive
  }

  override def render(g: Graphics, dxx: Int, dyy: Int): Unit = {
    if (alive) {

      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]
      g2d.setComposite(
        AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                                   Util.alpha(0.9f * (1 - lifeFactor))))

      if (up) {
        if (currentImage != null)
          g2d.drawImage(currentImage, x + dxx, y + dyy, width, height, null)
      } else {
        // flip horizontally
        if (currentImage != null)
          g2d.drawImage(currentImage,
                        x + dxx,
                        y + dyy + height,
                        width,
                        -height,
                        null)
      }
      g2d.dispose()
    }
  }

}


================================================
FILE: src/main/scala/de/ax/powermode/power/element/PowerIndicator.scala
================================================
package de.ax.powermode.power.element

import com.intellij.openapi.editor.Editor
import de.ax.powermode.power.ElementOfPower
import de.ax.powermode.{PowerMode, Util}
import squants.DimensionlessConversions.DimensionlessConversions

import java.awt._
import java.awt.image.BufferedImage
import scala.annotation.tailrec
import scala.collection.mutable
import scala.language.postfixOps
import scala.ref.WeakReference

/**
  * Created by nyxos on 25.02.17.
  */
object PowerIndicator {
  var indicators = mutable.Queue.empty[PowerIndicator]

  def addIndicator(i: PowerIndicator): Unit = {
    this.synchronized {
      PowerIndicator.indicators += i
      PowerIndicator.indicators = PowerIndicator.indicators.filter(i => i.alive)
    }
  }

  val grands = Seq("perfect",
                   "excellent",
                   "superb",
                   "sublime",
                   "dominating",
                   "marvelous",
                   "splendid",
                   "majestic",
                   "unreal",
                   "fabulous",
                   "great")

  var lastGrand = Option.empty[String]

  def genGrand: String = {
    @tailrec
    def nextGrand(lastGrand: Option[String]): String = {
      val grand = grands((Math.random() * 100023451).toInt % grands.length) + "!"
      if (lastGrand.contains(grand)) {
        nextGrand(lastGrand)
      } else {
        grand
      }
    }

    if (math.random * 100.percent < Seq(
          1.percent,
          0.2 * PowerMode.getInstance.valueFactor).max) {
      val grand = nextGrand(lastGrand)
      lastGrand = Some(grand)
      grand
    } else {
      ""
    }
  }
}

case class PowerIndicator(_x: Float,
                          _y: Float,
                          _width: Float,
                          _height: Float,
                          initLife: Long,
                          editor: WeakReference[Editor])
    extends ElementOfPower {
  val identifier = System.currentTimeMillis() + (Math.random() * 1000000)
  var diffLife = Option.empty[Long]
  var x: Double = _x
  var y: Double = _y
  var width: Double = 0
  var height: Double = 0
  PowerIndicator.addIndicator(this)
  val life2 = System.currentTimeMillis() + initLife
  val grand = PowerIndicator.genGrand

  override def life = {

    if (isLast) {
      math.max(life2.toDouble, System.currentTimeMillis() + (initLife * 0.75)) toLong
    } else {
      diffLife = Some(
        diffLife.getOrElse(
          System.currentTimeMillis() + (initLife * 0.75) toLong))
      diffLife.get
    }
  }

  def isLast: Boolean = {
    PowerIndicator.indicators != null && PowerIndicator.indicators.lastOption
      .filter(_ != null)
      .exists(i => identifier == i.identifier)
  }

  override def update(delta: Float): Boolean = {
    if (alive) {
      x = _x + (0.5 * _width) - (0.5 * _width * (1 - lifeFactor))
      y = _y + (0.5 * _height) - (0.5 * _height * (1 - lifeFactor))
      width = _width * (1 - lifeFactor)
      height = _height * (1 - lifeFactor)
    }
    !alive
  }

  var lastScrollPosition = Option.empty[(Int, Int)]

  override def render(g: Graphics, _dxx: Int, _dyy: Int): Unit = {
    def limit(v: Int, max: Int): Int = {
      //      if (v > max) max else if (v < -max) -max else v
      v
    }

    if (alive && powerMode.isEnabled && powerMode.powerIndicatorEnabled) {
      val Some((dxx, dyy)) = lastScrollPosition
        .map(lp => {
          val (nx, ny) =
            (editor.get.get.getScrollingModel.getHorizontalScrollOffset,
             editor.get.get.getScrollingModel.getVerticalScrollOffset)
          (lp._1 - nx, lp._2 - ny)
        })
        .orElse(Some(0, 0))
        .map { case (x, y) => (limit(x, 100), limit(y, 100)) }
      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]
      g2d.setComposite(
        AlphaComposite.getInstance(
          AlphaComposite.SRC_OVER,
          Util.alpha(1f * (1 - lifeFactor) * (1 - lifeFactor))))

      val bufferedImage =
        new BufferedImage(600, 600, BufferedImage.TYPE_INT_ARGB)
      val graphics = bufferedImage.getGraphics
      drawIndicator(graphics.asInstanceOf[Graphics2D],
                    bufferedImage.getWidth,
                    bufferedImage.getHeight)
      g2d.drawImage(bufferedImage,
                    math.max(x, 0) - dxx toInt,
                    math.max(y, 0) - dyy toInt,
                    width toInt,
                    height toInt,
                    null)
      g2d.dispose()
      lastScrollPosition = Some(
        (editor.get.get.getScrollingModel.getHorizontalScrollOffset,
         editor.get.get.getScrollingModel.getVerticalScrollOffset))
    }
  }

  private def drawIndicator(graphics: Graphics2D, width: Int, height: Int) = {
    graphics.setColor(Color.darkGray)
    graphics.fillRect(10, 10, width - 10, 200)
    graphics.setColor(Color.white)
    graphics.setFont(new Font("Dialog", Font.PLAIN, 100))
    graphics.drawString((powerMode.rawValueFactor * 100).toInt.toString + " %",
                        10,
                        100)
    graphics.setColor(Color.white)
    graphics.drawString(grand, 10, 200)
    graphics.setColor(Color.white)
    var f =
      math.min(powerMode.rawValueFactor, 20 + (powerMode.rawValueFactor % 1))
    var max: Double = math.ceil(f)
    val maxLines = 8

    val maxYSpace = 30 * maxLines / max
    var barHeight = math.min(50, 0.75 * maxYSpace) toInt
    var barSpace = math.min(17, 0.25 * maxYSpace) toInt

    while (f > 0) {
      graphics.setColor(Color.white)
      graphics.fillRect(10,
                        height - (((max.toInt + 1) - math
                          .ceil(f)) * (barSpace + barHeight)) toInt,
                        width * (if (f >= 1) 1 else f) - 10 toInt,
                        barHeight)
      graphics.setColor(Color.black)
      graphics.setStroke(new BasicStroke(10))
      graphics.drawRect(9,
                        height - (((max.toInt + 1) - math
                          .ceil(f)) * (barSpace + barHeight)) - 1 toInt,
                        width * (if (f >= 1) 1 else f) - 1 - 10 toInt,
                        barHeight - 1)
      f -= 1
    }
  }
}


================================================
FILE: src/main/scala/de/ax/powermode/power/element/PowerSpark.scala
================================================
/*
 * Copyright 2015 Baptiste Mesta
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.ax.powermode.power.element

import de.ax.powermode.Util
import de.ax.powermode.power.ElementOfPower
import powermode.PowerColor

import java.awt._

/**
  * @author Baptiste Mesta
  */
case class PowerSpark(var x: Float,
                      var y: Float,
                      dx: Float,
                      var dy: Float,
                      size: Float,
                      val initLife: Long,
                      color: PowerColor,
                      gravityFactor: Float)
    extends ElementOfPower {
  val life = System.currentTimeMillis() + initLife

  def update(delta: Float): Boolean = {
    dy += (0.07f * gravityFactor) * delta
    x += dx * delta
    y += dy * delta
    !alive
  }

  def render(g: Graphics, dxx: Int, dyy: Int): Unit = {
    if (alive) {
      val g2d: Graphics2D = g.create.asInstanceOf[Graphics2D]
      g2d.setColor(
        new Color(color._1, color._2, color._3, Util.alpha(color._4)))
      g2d.fillOval((dxx + x - (size / 2)).toInt,
                   (dyy + y - (size / 2)).toInt,
                   size.toInt,
                   size.toInt)
      g2d.dispose()
    }
  }

}


================================================
FILE: src/main/scala/de/ax/powermode/power/hotkeys/HotkeyHeatupListener.scala
================================================
package de.ax.powermode.power.hotkeys

import com.intellij.ide.DataManager
import com.intellij.openapi.actionSystem._
import com.intellij.openapi.components.ApplicationComponent
import com.intellij.openapi.keymap.KeymapManager
import com.intellij.openapi.wm.ToolWindowManager
import com.intellij.openapi.wm.ex.ToolWindowManagerListener
import com.intellij.util.{SlowOperations, ThrowableRunnable}
import de.ax.powermode.Power
import java.awt._
import java.awt.event._
import java.util
import javax.swing._

class HotkeyHeatupListener extends AWTEventListener with Power {

  lazy val allActionKeyStrokes: Set[KeyStroke] =
    actionsToKeyStrokes.values.flatten.toSet

  lazy val actionsToKeyStrokes = {
    Map(
      KeymapManager.getInstance.getActiveKeymap.getActionIds.toList
        .map(ActionManager.getInstance.getAction)
        .filter(a => a != null && a.getShortcutSet != null)
        .map { a =>
          val keyStrokes = a.getShortcutSet.getShortcuts.toList
            .filter(_.isKeyboard)
            .filter(_.isInstanceOf[KeyboardShortcut])
            .map(_.asInstanceOf[KeyboardShortcut])
            .flatMap(a => Seq(a.getFirstKeyStroke, a.getSecondKeyStroke))
          (a, keyStrokes)
        }: _*)
  }

  override def eventDispatched(e: AWTEvent): Unit = {
    SlowOperations.allowSlowOperations(new ThrowableRunnable[Exception] {
      override def run(): Unit = {
        if (powerMode.isEnabled && powerMode.isHotkeyHeatup) {
          e match {
            case event: KeyEvent => {
              if ((event.getModifiersEx & (InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK)) > 0) {

                val eventKeyStroke =
                  KeyStroke.getKeyStroke(event.getKeyCode, event.getModifiersEx)
                val isHotkey = allActionKeyStrokes.contains(eventKeyStroke)
                if (isHotkey) {
                  powerMode.increaseHeatup(
                    Option(
                      DataManager
                        .getInstance()
                        .getDataContext(event.getComponent)),
                    Option(eventKeyStroke))
                }
              }
            }
            case _ =>
          }
        }

      }
    })
  }
  Toolkit.getDefaultToolkit.addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK)
}


================================================
FILE: src/main/scala/de/ax/powermode/power/management/ElementOfPowerContainer.scala
================================================
/*
 * Copyright 2015 Baptiste Mesta
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.ax.powermode.power.management

import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.event._
import com.intellij.openapi.editor.{Editor, ScrollingModel}
import de.ax.powermode.power.ElementOfPower
import de.ax.powermode.power.element.{
  PowerBam,
  PowerFlame,
  PowerIndicator,
  PowerSpark
}
import de.ax.powermode.{Power, Util}
import powermode.PowerColor
import squants.Dimensionless
import squants.DimensionlessConversions.{
  DimensionlessConversions,
  dimensionlessToDouble,
  each
}
import squants.time.Time._
import squants.time.Frequency._
import squants.time.TimeConversions._
import squants.time.FrequencyConversions._
import squants.MetricSystem._
import squants.time.{Frequency, Time, TimeUnit}

import scala.language.postfixOps
import java.awt.event.{ComponentEvent, ComponentListener}
import java.awt.{Graphics, Point, Rectangle}
import java.util.TimerTask
import javax.swing._
import scala.jdk.CollectionConverters._
import scala.language.postfixOps
import scala.ref.WeakReference

object ElementOfPowerContainer {
  private val logger = Logger.getInstance(this.getClass)
}

/**
  * @author Baptiste Mesta
  */
class ElementOfPowerContainer(editor: WeakReference[Editor])
    extends JComponent
    with ComponentListener
    with Power {

  private val _myParent: Option[WeakReference[JComponent]] =
    editor.get.map(_.getContentComponent).map(WeakReference.apply)
  private def myParent: Option[JComponent] = _myParent.flatMap(_.get)
  myParent.foreach { myParent =>
    myParent.add(this)
    this.setBounds(myParent.getBounds)
    setVisible(true)
    myParent.addComponentListener(this)
  }

  val shakeComponents: Seq[JComponent] =
    Seq(editor.get.map(_.getComponent), editor.get.map(_.getContentComponent)).flatten
  var elementsOfPower: Seq[(ElementOfPower, (Int, Int))] = Seq.empty
  var lastShake: Long = System.currentTimeMillis()
  var shakeData: Option[(Int, Int, Int, Int)] = Option.empty

  var lastUpdate: Long = System.currentTimeMillis()

  var lastPositions: Seq[(Point, Point)] = Seq.empty
  editor.get.foreach(_.getCaretModel.addCaretListener(new CaretListener {

    def changeCarets: Unit = {
      lastPositions = {
        editor.get.toSeq.flatMap(editor =>
          editor.getCaretModel.getAllCarets.asScala.toSeq.map(caret => {
            (Util.getPoint(
               editor.offsetToVisualPosition(caret.getSelectionStart),
               caret.getEditor),
             Util.getPoint(editor.offsetToVisualPosition(caret.getSelectionEnd),
                           caret.getEditor))
          }))
      }
    }

    override def caretPositionChanged(e: CaretEvent): Unit = changeCarets

    override def caretAdded(e: CaretEvent): Unit = changeCarets

    override def caretRemoved(e: CaretEvent): Unit = changeCarets
  }))
  private val self: ElementOfPowerContainer = this

  editor.get.foreach(_.getDocument.addDocumentListener(new DocumentListener {
    val wr: WeakReference[ElementOfPowerContainer] = WeakReference(self)
    override def documentChanged(documentEvent: DocumentEvent): Unit = {

      wr.get match {
        case Some(elementOfPowerContainer) =>
          elementOfPowerContainer.initializeCaretBam(documentEvent)
        case None => documentEvent.getDocument.removeDocumentListener(this)
      }
    }
  }))

  private def initializeCaretBam(e: DocumentEvent) = {
    if (powerMode.isBamEnabled) {
      editor.get.foreach { editor =>
        val shouldAnimate = {
          e.getNewFragment.length() > 100 ||
          e.getOldFragment.length() > 100 ||
          e.getOldFragment.toString.count('\n' == _) > 1 ||
          e.getNewFragment.toString.count('\n' == _) > 1
        }
        if (shouldAnimate) {
          val width = {
            val l = (e.getOldFragment.toString + e.getNewFragment.toString)
              .split("\n")
            if (l.nonEmpty) {
              (l.maxBy(_.length).length / 2.0) * editor.getLineHeight
            } else {
              0
            }
          }
          val timer = new java.util.Timer()
          timer.schedule(new TimerTask {
            override def run(): Unit = {
              SwingUtilities.invokeLater(() => {
                performCaretBam(width)
              })
            }
          }, 300)
        }
      }
    }
  }

  private def performCaretBam(width: Double) = {
    if (lastPositions.nonEmpty) {
      editor.get.foreach { editor =>
        val myLastPositions = lastPositions
        SwingUtilities.invokeLater(() => {
          myLastPositions.foreach {
            case (a, b) =>
              val w = editor.getComponent.getWidth.toDouble
              val h = editor.getComponent.getHeight.toDouble
              initializeAnimation(a,
                                  new Point(math.min(0, b.x), math.min(0, b.y)),
                                  width)
          }
        })
      }
    }
  }

  def getAllCaretPositions: Seq[Point] = {

    editor.get.toList.flatMap { editor =>
      editor.getCaretModel.getAllCarets.asScala.toSeq.map(caret =>
        Util.getPoint(caret.getVisualPosition, caret.getEditor))
    }
  }

  def updateElementsOfPower(): Unit = {
    var delta = (System.currentTimeMillis() - lastUpdate)
    val value = (1000.0 / powerMode.frameRate.toHertz)
    if (delta > value * 2) {
      //smoothen movement when frame rate drops
      delta = 16
    }
    lastUpdate = System.currentTimeMillis()
    val db: Double = 1000.0 / 16
    if (elementsOfPower.nonEmpty) {
      elementsOfPower =
        elementsOfPower.filterNot(p => p._1.update((delta / db).toFloat))
      repaint()
    }
  }

  def addPowerIndicator(): Unit = {
    val indicatorWidth = 100
    elementsOfPower :+= (PowerIndicator(
      (getMyBounds.width - 20 - indicatorWidth).toFloat,
      (getMyBounds.height - 20 - indicatorWidth).toFloat,
      indicatorWidth.toFloat,
      indicatorWidth.toFloat,
      1000L,
      editor
    ), getScrollPosition)
  }

  def initializeAnimation(point: Point): Unit = {

    this.setBounds(getMyBounds)

    if (powerMode.isSparksEnabled) {
      addSparks(point)
    }
    if (powerMode.isFlamesEnabled) {
      addFlames(point)
    }

    if (powerMode.isShakeEnabled) {
      doShake(shakeComponents)
    }
    repaint()

  }

  def initializeAnimation(a: Point, b: Point, lineWidth: Double): Unit = {
    val x = a.x
    var y = a.y
    val width = math.max(b.x - x, 50)
    val height = math.max(b.y - y, 50)
    val dim =
      (Seq(
        Seq(lineWidth.toInt, width, height, 50).max,
        editor.get.get.getComponent.getWidth,
        editor.get.get.getComponent.getHeight).min * powerMode.valueFactor).toInt
    if (b.y - y.abs < dim) {
      y = y - dim / 2
    }
    elementsOfPower :+= (PowerBam(
      math.max(0, x).toFloat,
      math.max(0, y).toFloat,
      dim.toFloat,
      dim.toFloat,
      (powerMode.bamLife * powerMode.valueFactor).toMilliseconds.toLong), getScrollPosition)
  }

  def addFlames(point: Point): Unit = {
    val base = 0.3
    val wh = (powerMode.maxFlameSize * base +
      ((math.random * powerMode.maxFlameSize * (1 - base)) * powerMode.valueFactor)).toInt
    val initLife =
      (powerMode.maxFlameLife * powerMode.valueFactor).toMilliseconds.toInt
    if (initLife > 100) {
      elementsOfPower :+= (PowerFlame(point.x + 5,
                                      point.y - 1,
                                      wh,
                                      wh,
                                      initLife,
                                      true), getScrollPosition)
      elementsOfPower :+= (PowerFlame(point.x + 5,
                                      point.y + 15,
                                      wh,
                                      wh,
                                      initLife,
                                      false), getScrollPosition)
    }
  }

  def addSparks(point: Point): Unit = {
    for (i <- 0 to (powerMode.sparkCount * powerMode.valueFactor).toInt) {
      addSpark(point.x, point.y)
    }
  }

  def addSpark(x: Int, y: Int): Unit = {
    val dx
      : Double = (Math.random * 2) * (if (Math.random > 0.5) -1 else 1) * powerMode.sparkVelocityFactor
    val dy: Double = ((Math.random * -3) - 1) * powerMode.sparkVelocityFactor
    val size = ((Math.random * powerMode.sparkSize) + 1).toInt
    val life = Math.random() * powerMode.getSparkLife * powerMode.valueFactor
    val powerSpark = PowerSpark(x.toFloat,
                                y.toFloat,
                                dx.toFloat,
                                dy.toFloat,
                                size.toFloat,
                                life.toLong,
                                genNextColor,
                                powerMode.gravityFactor.toFloat)
    elementsOfPower :+= (powerSpark, getScrollPosition)
  }

  def genNextColor: PowerColor =
    (getColorPart(powerMode.getRedFrom, powerMode.getRedTo),
     getColorPart(powerMode.getGreenFrom, powerMode.getGreenTo),
     getColorPart(powerMode.getBlu
Download .txt
gitextract_08n_przv/

├── .gitignore
├── .scalafmt.conf
├── LICENSE
├── README.md
├── build.sbt
├── log4j.xml
├── project/
│   ├── build.properties
│   └── plugins.sbt
├── resources/
│   └── META-INF/
│       └── plugin.xml
└── src/
    └── main/
        ├── java/
        │   ├── de/
        │   │   └── ax/
        │   │       └── powermode/
        │   │           └── power/
        │   │               ├── color/
        │   │               │   ├── ColorViewController.java
        │   │               │   ├── MultiGradientPanel.java
        │   │               │   ├── UiTest.form
        │   │               │   └── UiTest.java
        │   │               └── ui/
        │   │                   ├── PowerModeConfigurableUI.form
        │   │                   ├── PowerModeConfigurableUI.java
        │   │                   └── ValueSettable.java
        │   └── javazoom/
        │       └── jl/
        │           └── player/
        │               └── HackyJavaSoundAudioDevice.java
        └── scala/
            └── de/
                └── ax/
                    └── powermode/
                        ├── ImageUtil.scala
                        ├── MyCaretListener.scala
                        ├── MyTypedActionHandler.scala
                        ├── NextSongAction.scala
                        ├── Power.scala
                        ├── PowerMode.scala
                        ├── PowerModeConfigurable.scala
                        ├── PowerModeStartup.scala
                        ├── TogglePowerMode.scala
                        ├── Util.scala
                        ├── cache/
                        │   └── Cache.scala
                        ├── package.scala
                        └── power/
                            ├── ElementOfPower.scala
                            ├── color/
                            │   ├── ColorEdges.scala
                            │   └── MyPaint.scala
                            ├── element/
                            │   ├── PowerBam.scala
                            │   ├── PowerFlame.scala
                            │   ├── PowerIndicator.scala
                            │   └── PowerSpark.scala
                            ├── hotkeys/
                            │   └── HotkeyHeatupListener.scala
                            ├── management/
                            │   ├── ElementOfPowerContainer.scala
                            │   └── ElementOfPowerContainerManager.scala
                            └── sound/
                                ├── MediaPlayer.scala
                                └── PowerSound.scala
Download .txt
SYMBOL INDEX (48 symbols across 6 files)

FILE: src/main/java/de/ax/powermode/power/color/ColorViewController.java
  class ColorViewController (line 8) | public class ColorViewController {
    method genX (line 15) | public double genX() {
    method ColorViewController (line 19) | public ColorViewController(MultiGradientPanel colorView, PowerMode pow...

FILE: src/main/java/de/ax/powermode/power/color/MultiGradientPanel.java
  class MultiGradientPanel (line 8) | public class MultiGradientPanel extends JPanel {
    method setColorEdges (line 11) | public void setColorEdges(ColorEdges colorEdges) {
    method MultiGradientPanel (line 18) | public MultiGradientPanel(int size, ColorEdges colorEdges) {
    method paintComponent (line 26) | @Override
    method doUpdate (line 55) | public void doUpdate(double c) {

FILE: src/main/java/de/ax/powermode/power/color/UiTest.java
  class UiTest (line 9) | public class UiTest {
    method main (line 18) | public static void main(String[] args) {
    method createUIComponents (line 31) | private void createUIComponents() {
    method $$$setupUI$$$ (line 50) | private void $$$setupUI$$$() {
    method $$$getRootComponent$$$ (line 60) | public JComponent $$$getRootComponent$$$() {

FILE: src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.java
  class PowerModeConfigurableUI (line 24) | public class PowerModeConfigurableUI implements ConfigurableUi<PowerMode> {
    method PowerModeConfigurableUI (line 92) | public PowerModeConfigurableUI(PowerMode powerMode) {
    method validateImagePath (line 231) | private boolean validateImagePath(PowerMode powerMode, JTextField flam...
    method bindSlieders (line 245) | private void bindSlieders(JSlider from, JSlider to) {
    method initValuesColor (line 264) | private void initValuesColor(int initValue, JSlider slider, JLabel sli...
    method initValues (line 272) | private void initValues(int initValue, JSlider slider, JLabel sliderVa...
    method reset (line 283) | @Override
    method isModified (line 288) | @Override
    method apply (line 293) | @Override
    method getComponent (line 299) | @Override
    method createUIComponents (line 304) | private void createUIComponents() {
    method $$$setupUI$$$ (line 317) | private void $$$setupUI$$$() {
    method $$$getRootComponent$$$ (line 651) | public JComponent $$$getRootComponent$$$() {
    type ValueColorSettable (line 655) | private interface ValueColorSettable {
      method setValue (line 656) | void setValue(JSlider slider);
    class MyChangeListener (line 659) | private abstract class MyChangeListener implements ChangeListener, Val...
      method MyChangeListener (line 663) | public MyChangeListener(JSlider slider, JLabel jLabel) {
      method stateChanged (line 668) | @Override

FILE: src/main/java/de/ax/powermode/power/ui/ValueSettable.java
  type ValueSettable (line 8) | public interface ValueSettable {
    method setValue (line 9) | void setValue(JSlider slider);

FILE: src/main/java/javazoom/jl/player/HackyJavaSoundAudioDevice.java
  class HackyJavaSoundAudioDevice (line 44) | public class HackyJavaSoundAudioDevice extends AudioDeviceBase {
    method setAudioFormat (line 51) | protected void setAudioFormat(AudioFormat fmt0) {
    method getAudioFormat (line 55) | protected AudioFormat getAudioFormat() {
    method getSourceLineInfo (line 67) | protected DataLine.Info getSourceLineInfo() {
    method open (line 74) | public void open(AudioFormat fmt) throws JavaLayerException {
    method openImpl (line 82) | protected void openImpl()
    method createSource (line 88) | protected void createSource() throws JavaLayerException {
    method millisecondsToBytes (line 115) | public int millisecondsToBytes(AudioFormat fmt, int time) {
    method closeImpl (line 119) | protected void closeImpl() {
    method writeImpl (line 125) | protected void writeImpl(short[] samples, int offs, int len)
    method getByteArray (line 134) | protected byte[] getByteArray(int length) {
    method toByteArray (line 141) | protected byte[] toByteArray(short[] samples, int offs, int len) {
    method flushImpl (line 153) | protected void flushImpl() {
    method getPosition (line 159) | public int getPosition() {
    method test (line 170) | public void test()
Condensed preview — 41 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (221K chars).
[
  {
    "path": ".gitignore",
    "chars": 49,
    "preview": ".idea\nout\n*.iml\n*.jar\nlib/\n*.zip\n**/target\n.bsp/\n"
  },
  {
    "path": ".scalafmt.conf",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "LICENSE",
    "chars": 11324,
    "preview": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licens"
  },
  {
    "path": "README.md",
    "chars": 3213,
    "preview": "Power Mode II Intellij plugin\n======================\n\n[![Join the chat at https://gitter.im/baptistemesta/power-mode-int"
  },
  {
    "path": "build.sbt",
    "chars": 1353,
    "preview": "import org.jetbrains.sbtidea.Keys._\n\nlazy val powerMode =\n  project\n    .in(file(\".\"))\n    .enablePlugins(SbtIdeaPlugin)"
  },
  {
    "path": "log4j.xml",
    "chars": 717,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n\n<log4j:configuration xmlns:lo"
  },
  {
    "path": "project/build.properties",
    "chars": 18,
    "preview": "sbt.version=1.4.3\n"
  },
  {
    "path": "project/plugins.sbt",
    "chars": 61,
    "preview": "addSbtPlugin(\"org.jetbrains\" % \"sbt-idea-plugin\" % \"3.18.3\")\n"
  },
  {
    "path": "resources/META-INF/plugin.xml",
    "chars": 3827,
    "preview": "<idea-plugin>\n    <id>de.ax.powermode</id>\n    <name>Power Mode II</name>\n    <version>105.501</version>\n    <vendor ema"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/ColorViewController.java",
    "chars": 1571,
    "preview": "package de.ax.powermode.power.color;\n\nimport de.ax.powermode.PowerMode;\n\n/**\n * Created by nyxos on 05.07.16.\n */\npublic"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/MultiGradientPanel.java",
    "chars": 1713,
    "preview": "package de.ax.powermode.power.color;\n\nimport javax.swing.*;\nimport java.awt.*;\nimport java.awt.geom.Point2D;\n\n\npublic cl"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/UiTest.form",
    "chars": 825,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class="
  },
  {
    "path": "src/main/java/de/ax/powermode/power/color/UiTest.java",
    "chars": 1469,
    "preview": "package de.ax.powermode.power.color;\n\nimport javax.swing.*;\nimport java.awt.*;\n\n/**\n * Created by nyxos on 21.06.16.\n */"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.form",
    "chars": 54762,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<form xmlns=\"http://www.intellij.com/uidesigner/form/\" version=\"1\" bind-to-class="
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/PowerModeConfigurableUI.java",
    "chars": 50328,
    "preview": "package de.ax.powermode.power.ui;\n\nimport com.intellij.openapi.options.ConfigurableUi;\nimport com.intellij.openapi.optio"
  },
  {
    "path": "src/main/java/de/ax/powermode/power/ui/ValueSettable.java",
    "chars": 169,
    "preview": "package de.ax.powermode.power.ui;\n\nimport javax.swing.*;\n\n/**\n * Created by nyxos on 11.03.16.\n */\npublic interface Valu"
  },
  {
    "path": "src/main/java/javazoom/jl/player/HackyJavaSoundAudioDevice.java",
    "chars": 5684,
    "preview": "/*\n * 11/26/04\t\tBuffer size modified to support JRE 1.5 optimizations.\n *              (CPU usage < 1% under P4/2Ghz, RA"
  },
  {
    "path": "src/main/scala/de/ax/powermode/ImageUtil.scala",
    "chars": 6097,
    "preview": "package de.ax.powermode\n\nimport com.intellij.util.PathUtil\nimport de.ax.powermode.cache.Cache\nimport de.ax.powermode.pow"
  },
  {
    "path": "src/main/scala/de/ax/powermode/MyCaretListener.scala",
    "chars": 1351,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.editor.Caret\nimport com.intellij.openapi.editor.event.{CaretEvent, "
  },
  {
    "path": "src/main/scala/de/ax/powermode/MyTypedActionHandler.scala",
    "chars": 1526,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.DataContext\nimport com.intellij.openapi.editor.Editor\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/NextSongAction.scala",
    "chars": 370,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}\n\n/**\n  * Created by nyxos on"
  },
  {
    "path": "src/main/scala/de/ax/powermode/Power.scala",
    "chars": 178,
    "preview": "package de.ax.powermode\n\n/**\n  * Created by nyxos on 04.01.17.\n  */\ntrait Power {\n  def powerMode: PowerMode = {\n    Pow"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerMode.scala",
    "chars": 15169,
    "preview": "/*\n * Copyright 2015 Baptiste Mesta\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerModeConfigurable.scala",
    "chars": 1240,
    "preview": "/*\n * Copyright 2015 Baptiste Mesta\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
  },
  {
    "path": "src/main/scala/de/ax/powermode/PowerModeStartup.scala",
    "chars": 570,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.project.Project\nimport com.intellij.openapi.startup.StartupActivity"
  },
  {
    "path": "src/main/scala/de/ax/powermode/TogglePowerMode.scala",
    "chars": 291,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}\n\n/**\n  * Created by nyxos on"
  },
  {
    "path": "src/main/scala/de/ax/powermode/Util.scala",
    "chars": 1998,
    "preview": "package de.ax.powermode\n\nimport com.intellij.openapi.editor.impl.EditorImpl\nimport com.intellij.openapi.editor.{Caret, E"
  },
  {
    "path": "src/main/scala/de/ax/powermode/cache/Cache.scala",
    "chars": 671,
    "preview": "package de.ax.powermode.cache\n\nimport scala.collection.mutable;\n\nclass Cache[K, V, I](compareValue: K => I, shoudUpdate:"
  },
  {
    "path": "src/main/scala/de/ax/powermode/package.scala",
    "chars": 122,
    "preview": "/**\n  * Created by nyxos on 13.03.16.\n  */\npackage object powermode {\n\n  type PowerColor = (Float, Float, Float, Float)\n"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/ElementOfPower.scala",
    "chars": 530,
    "preview": "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"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/color/ColorEdges.scala",
    "chars": 2358,
    "preview": "package de.ax.powermode.power.color\n\nimport java.awt.Color\n\nclass ColorEdges(var leftTop: MyPaint = MyPaint(0, 0, 0, 255"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/color/MyPaint.scala",
    "chars": 366,
    "preview": "package de.ax.powermode.power.color\n\nimport java.awt.Color\n\n/**\n  * Created by nyxos on 05.07.16.\n  */\ncase class MyPain"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerBam.scala",
    "chars": 2492,
    "preview": "package de.ax.powermode.power.element\n\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.{ImageUtil, Ut"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerFlame.scala",
    "chars": 1918,
    "preview": "package de.ax.powermode.power.element\n\nimport de.ax.powermode.power.ElementOfPower\nimport de.ax.powermode.{ImageUtil, Ut"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerIndicator.scala",
    "chars": 6143,
    "preview": "package de.ax.powermode.power.element\n\nimport com.intellij.openapi.editor.Editor\nimport de.ax.powermode.power.ElementOfP"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/element/PowerSpark.scala",
    "chars": 1731,
    "preview": "/*\n * Copyright 2015 Baptiste Mesta\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/hotkeys/HotkeyHeatupListener.scala",
    "chars": 2322,
    "preview": "package de.ax.powermode.power.hotkeys\n\nimport com.intellij.ide.DataManager\nimport com.intellij.openapi.actionSystem._\nim"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/management/ElementOfPowerContainer.scala",
    "chars": 12732,
    "preview": "/*\n * Copyright 2015 Baptiste Mesta\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/management/ElementOfPowerContainerManager.scala",
    "chars": 5610,
    "preview": "/*\n * Copyright 2015 Baptiste Mesta\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/sound/MediaPlayer.scala",
    "chars": 3955,
    "preview": "package de.ax.powermode.power.sound\n\nimport com.intellij.openapi.diagnostic.Logger\nimport de.ax.powermode.PowerMode\nimpo"
  },
  {
    "path": "src/main/scala/de/ax/powermode/power/sound/PowerSound.scala",
    "chars": 2439,
    "preview": "package de.ax.powermode.power.sound\n\nimport de.ax.powermode.Power\nimport javazoom.jl.player.{FactoryRegistry, HackyJavaS"
  }
]

About this extraction

This page contains the full source code of the axaluss/power-mode-intellij-plugin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 41 files (204.4 KB), approximately 50.5k tokens, and a symbol index with 48 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!