| name | new-visualizer |
| description | Adds a new full-screen visualizer to the application, with optional configuration options. |
What this skill does
- Adds a new full-screen visualizer to the application.
- Publishes the new visualizer to the application so that it can be presented as an option to the user.
- Optionally publishes configuration properties for the new visualizer so that the user can customize its behavior or appearance.
Visualizer overview
The ca.corbett.musicplayer.ui.VisualizationManager class contains a static abstract Visualizer class that serves
as the starting point for all visualizers. We need to extend this class and provide the functionality that is specific
to the new visualizer. The ca.corbett.musicplayer.extensions.builtin.ExtraVisualizers class contains a couple of
example implementations. The RollingWaveVisualizer is a good example to follow. That visualizer defines a few
configuration options, uses the initialize() method to prepare for visualization, and then implements the
renderFrame() method to update the gradient and display it efficiently.
Not all visualizers will expose configuration options. If a visualizer needs to expose configuration options,
it can use any of the *Property classes from the ca.corbett.extras.properties package in the
swing-extras library. A property wrapper class exists for most common types of properties:
BooleanProperty: wraps a simple yes/no or on/off option, represented as a checkbox in the UI.
ShortTextProperty: a single-line text input field.
LongTextProperty: a multi-line text input field.
IntegerProperty: for selecting a whole number from a defined range. Example: TCP port selection.
DecimalProperty: for selecting a floating-point number from a defined range.
ColorProperty: can be used to select a single color, or a color gradient (using a custom gradient color chooser)
FontProperty: for selecting a font, with optional style selection and foreground/background color choosers.
ComboProperty: for selecting an item from a predefined list of options.
EnumProperty: for selecting a specific enum value from a caller-defined enum.
These property classes all extend AbstractProperty, so our visualizer can simply offer a List<AbstractProperty>
and the parent application will know what to do with it.
Step-by-step instructions
- Add a new static inner class to
ExtraVisualizers
- Add a no-arg constructor that passes a name to the parent constructor. The name should be short, unique, and descriptive (this is a user-facing name).
- Override
initialize() to do any heavy setup (IO or CPU intensive operations)
- Override
renderFrame() to render each individual frame. This code should ideally be performance-optimized.
- Optionally offer a
List<AbstractProperty> representing configuration options. It's okay if there are none to offer.
- Make sure that the
getCustomVisualizers() method in ExtraVisualizers returns an instance of the new Visualizer. This is how the parent application is made aware of the visualizer, so it can be presented as an option to the user.
- If configuration options are added, ensure the
createConfigProperties() method in ExtraVisualizers publishes them to the application.
- Visualizers in this application typically don't get unit tests. You can omit unit tests safely.
- Compile the project to ensure it builds successfully. Optionally run unit tests to make sure nothing is broken.
- Report success to the user.
Rendering graphics
You have access to a Graphics2D instance each time your renderFrame() method is invoked. Don't dispose this graphics
instance, as it is used in the animation loop!
You can make use of any of the standard drawing primitives offered by Java's Graphics2D API.