Icons
This guide explains how to add new icons to OpenRocket and how the icon theming system works.
Icon System Overview
OpenRocket uses a dynamic icon theming system that allows icons to automatically adapt their colors when the user
switches themes (Light, Dark, Dark Contrast). The system is built on top of FlatLaf’s FlatSVGIcon and uses
color filters to map placeholder colors in SVG files to theme-specific colors defined in property files.
Key files:
swing/src/main/java/info/openrocket/swing/gui/util/Icons.java- Icon definitions and loading logicswing/src/main/resources/themes/FlatLightLaf.properties- Light theme colorsswing/src/main/resources/themes/FlatDarculaLaf.properties- Dark theme colorsswing/src/main/resources/themes/FlatOneDarkIJTheme.properties- Dark Contrast theme colors
Adding a New SVG Icon
Step 1: Download the SVG
We primarily use Lucide Icons for SVG icons. To download an icon:
Search for the desired icon on https://lucide.dev/icons
Configure the export settings:
Color:
#000000(black - this is the default theme color placeholder)Stroke width:
1.25pxSize:
16pxAbsolute stroke width: Disabled
Download the SVG file
Place the SVG in
swing/src/main/resources/pix/icons/lucide/
Note
Verify that the SVG uses stroke="#000000" for strokes you want themed. Sometimes the export doesn’t
work correctly and you may need to manually edit the SVG file.
Step 2: Register the Icon
Add the icon definition to Icons.java. There are several methods available depending on your needs:
Simple monochrome icon (most common):
public static final Icon MY_ICON = loadIcon(
"pix/icons/lucide/my-icon.svg",
"pix/icons/my-icon-fallback.png", // PNG fallback (optional, can be same as SVG path)
"My Icon Description");
This uses the default color (OR.icons.default) which is black in light theme and white in dark theme.
Icon with custom theme color:
public static final Icon MY_ICON = loadIcon(
"pix/icons/lucide/my-icon.svg",
"pix/icons/my-icon-fallback.png",
"My Icon Description",
"OR.icons.myColor"); // UIManager color key
Icon with multiple colors (see Multi-Color Icons):
public static final Icon MY_ICON = loadIcon(
"pix/icons/lucide/my-icon.svg",
"pix/icons/my-icon-fallback.png",
"My Icon Description",
Map.of(
SVG_THEME_COLOR_RGB, SVG_DEFAULT_COLOR_KEY,
0x499C54, "OR.icons.plus"
));
SVG-only icon (no PNG fallback):
public static final Icon MY_ICON = loadSvgIcon(
"pix/icons/lucide/my-icon.svg",
"My Icon Description");
Scaled icon (for sub-icons or smaller variations):
public static final Icon MY_SMALL_ICON = loadIcon(
"pix/icons/lucide/my-icon.svg",
"pix/icons/my-icon-fallback.png",
"My Small Icon",
"OR.icons.myColor",
0.75); // 75% of normal size
How the Color Filter Works
The icon color filter is what makes icons adapt to theme changes dynamically. Here’s how it works:
Color Mapping Concept
When you load an SVG icon with color mappings, you’re telling the system:
“When you encounter this specific RGB color in the SVG, replace it with the color from this UIManager key.”
The mapping is defined as:
Map.of(
0x000000, "OR.icons.default", // Black in SVG -> OR.icons.default color
0x499C54, "OR.icons.plus" // Green (#499C54) in SVG -> OR.icons.plus color
)
First value (hex integer): The RGB color value stored in the SVG file (e.g.,
0x000000for black)Second value (String): The UIManager color key from the theme property files
Dynamic Resolution
The color filter resolves colors at paint time, not at icon creation time. This means:
When the theme changes,
UIManagercolors are updatedThe next time the icon paints, it queries
UIManagerfor the current colorIcons automatically reflect the new theme without needing to be recreated
This is implemented using a mapper function in createSvgColorFilter():
Function<Color, Color> colorMapper = originalColor -> {
int rgb = originalColor.getRGB() & 0x00ffffff;
String colorKey = rgbToKeyMap.get(rgb);
if (colorKey == null) {
return originalColor; // No mapping, keep original
}
Color themedColor = UIManager.getColor(colorKey);
// ... fallback logic ...
return themedColor;
};
Multi-Color SVG Icons
For icons with multiple distinct colors (e.g., a file icon with a green plus sign), you can map each color to a different theme key.
Creating a Multi-Color SVG
Design your SVG with specific placeholder colors for each element:
Use
#000000(black) for the main icon shape (maps toOR.icons.default)Use other colors like
#499C54(green),#2D2DBD(blue),#FAC132(yellow) for accents
Register the icon with a color map:
public static final Icon FILE_NEW = loadIcon(
"pix/icons/lucide/file-plus-corner.svg",
"pix/icons/document-new.png",
"New document",
Map.of(
SVG_THEME_COLOR_RGB, SVG_DEFAULT_COLOR_KEY, // 0x000000 -> OR.icons.default
0x499C54, "OR.icons.plus" // Green accent -> OR.icons.plus
));
Common Color Placeholders
When creating multi-color SVGs, use these standardized placeholder colors:
Hex Color |
Purpose |
Typical Theme Key |
|---|---|---|
|
Main icon color |
|
|
Green accents (plus, add, success) |
|
|
Blue accents (info, tint) |
|
|
Yellow accents (edit, pencil) |
|
|
Red accents (delete, remove, error) |
|
|
Gold accents (lock, favorite) |
|
Theme Property Files
Icon colors are defined in the theme property files under swing/src/main/resources/themes/.
Adding a New Icon Color
Define the color in all three theme files:
FlatLightLaf.properties (Light theme):
OR.icons.myNewColor = #2D7FF9
FlatDarculaLaf.properties (Dark theme):
OR.icons.myNewColor = #6EA8FE
FlatOneDarkIJTheme.properties (Dark Contrast theme):
OR.icons.myNewColor = #7EAAFF
Use the key in your icon definition:
public static final Icon MY_ICON = loadIcon(
"pix/icons/lucide/my-icon.svg",
"pix/icons/my-icon.png",
"My Icon",
"OR.icons.myNewColor");
Available Icon Color Keys
The following OR.icons.* keys are predefined:
Key |
Purpose |
|---|---|
|
Default icon color (black/white depending on theme) |
|
General accent color (blue) |
|
Play/run buttons (green) |
|
Help/info icons (blue) |
|
Low priority warnings (info color) |
|
Normal warnings (warning color) |
|
Critical warnings (error color) |
|
Override indicators |
|
Subcomponent override indicators (dimmed) |
|
Lock icon accent (gold) |
|
Delete/trash icons (red) |
|
Plot/chart icons (blue) |
|
Add/plus icons (green) |
|
Duplicate icons (tint color) |
|
Edit/pencil icons (yellow) |
|
Zoom in (green) |
|
Zoom out (red) |
|
Zoom to fit (tint color) |
|
Import icons (red) |
|
Export icons (green) |
|
Move up arrows (blue) |
|
Move down arrows (purple) |
|
Undo icons (red) |
|
Redo icons (blue) |
You can also reference other color keys using FlatLaf’s $ syntax:
OR.icons.myColor = $OR.colors.blue
Best Practices
Always use black (``#000000``) as the primary color - This is the default theme color and ensures icons work correctly even without explicit color mappings.
Keep SVGs simple - Use stroke-based icons with minimal complexity for best scaling and theming.
Test in all themes - After adding an icon, switch between Light, Dark, and Dark Contrast themes to verify colors look correct.
Maintain consistency - Use the predefined
OR.icons.*color keys when possible to maintain visual consistency across the application.Update all theme files - When adding a new color key, define it in all three theme property files.
Provide PNG fallbacks - While SVG is preferred, provide a PNG fallback for compatibility.
Use appropriate sizes - Icons are automatically scaled based on font size. Use the
scaleMultiplierparameter only when you need an icon that’s intentionally smaller or larger than the standard size.
Troubleshooting
Icon colors don’t update when switching themes
Ensure you’re using the Map.of() syntax for color mappings, not hardcoded colors. The color filter must
resolve colors dynamically from UIManager.
Icon appears with wrong colors
Verify the hex color in the SVG matches exactly what you specified in the color map
Check that the color key exists in all theme property files
Open the SVG in a text editor and verify the stroke/fill colors are correct
Icon is too large or too small
Icons are scaled based on the user’s font size setting. If you need a specifically sized icon, use the
scaleMultiplier parameter:
loadIcon(svgFile, pngFile, name, colorKey, 0.75); // 75% of normal size
SVG stroke colors not theming correctly
Make sure the SVG uses stroke="#000000" (or your placeholder color) and not stroke="black" or
other color formats. The color filter matches exact RGB values.