Stub out previous undo implementation; update docs.
- Remove outdated `undo-state.md` - Add two code quality/optimization reports that were used to guide previous work: - `code-report.md` (optimization) - `code-report-quality.md` (stability and code health) - Add `themes.md`. - Update undo system docs and roadmap.
This commit is contained in:
511
docs/themes.md
Normal file
511
docs/themes.md
Normal file
@@ -0,0 +1,511 @@
|
||||
Themes in kte
|
||||
=============
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
kte's GUI frontend (kge) uses ImGui for rendering and supports multiple
|
||||
color themes. Themes define the visual appearance of the editor
|
||||
interface including colors for text, backgrounds, buttons, borders, and
|
||||
other UI elements.
|
||||
|
||||
Theme files are located in the `themes/` directory and are header-only
|
||||
C++ files that configure ImGui's style system.
|
||||
|
||||
Available themes
|
||||
----------------
|
||||
|
||||
Current themes (alphabetically):
|
||||
|
||||
- **amber** — Monochrome amber/black CRT-inspired theme
|
||||
- **eink** — E-ink inspired high-contrast theme (light/dark variants)
|
||||
- **everforest** — Warm, forest-inspired palette
|
||||
- **gruvbox** — Retro groove color scheme (light/dark variants)
|
||||
- **kanagawa-paper** — Inspired by traditional Japanese art
|
||||
- **lcars** — Star Trek LCARS interface style
|
||||
- **nord** — Arctic, north-bluish color palette
|
||||
- **old-book** — Sepia-toned vintage book aesthetic (light/dark
|
||||
variants)
|
||||
- **orbital** — Space-themed dark palette
|
||||
- **plan9** — Minimalist Plan 9 from Bell Labs inspired
|
||||
- **solarized** — Ethan Schoonover's Solarized (light/dark variants)
|
||||
- **weyland-yutani** — Alien franchise corporate aesthetic
|
||||
- **zenburn** — Low-contrast, easy-on-the-eyes theme
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Themes are configured via `$HOME/.config/kte/kge.ini`:
|
||||
|
||||
```ini
|
||||
theme = nord
|
||||
background = dark
|
||||
```
|
||||
|
||||
- `theme` — The theme name (e.g., "nord", "gruvbox", "solarized")
|
||||
- `background` — Either "dark" or "light" (for themes supporting both
|
||||
variants)
|
||||
|
||||
Themes can also be switched at runtime using the `:theme <name>`
|
||||
command.
|
||||
|
||||
Theme structure
|
||||
---------------
|
||||
|
||||
Each theme is a header file in `themes/` that defines one or more
|
||||
functions to apply the theme. The basic structure:
|
||||
|
||||
1. **Include ThemeHelpers.h** — Provides the `RGBA()` helper function
|
||||
2. **Define palette** — Create `ImVec4` color constants using
|
||||
`RGBA(0xRRGGBB)`
|
||||
3. **Get ImGui style** — Obtain reference via `ImGui::GetStyle()`
|
||||
4. **Set style parameters** — Configure padding, rounding, border sizes,
|
||||
etc.
|
||||
5. **Assign colors** — Map palette to `ImGuiCol_*` enum values
|
||||
|
||||
### Minimal example structure
|
||||
|
||||
```cpp
|
||||
// themes/MyTheme.h
|
||||
#pragma once
|
||||
#include "ThemeHelpers.h"
|
||||
|
||||
static void
|
||||
ApplyMyTheme()
|
||||
{
|
||||
// 1. Define color palette
|
||||
const ImVec4 bg = RGBA(0x1e1e1e);
|
||||
const ImVec4 fg = RGBA(0xd4d4d4);
|
||||
const ImVec4 accent = RGBA(0x007acc);
|
||||
|
||||
// 2. Get style reference
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
|
||||
// 3. Set style parameters
|
||||
style.WindowPadding = ImVec2(8.0f, 8.0f);
|
||||
style.FrameRounding = 3.0f;
|
||||
style.WindowBorderSize = 1.0f;
|
||||
// ... additional style parameters
|
||||
|
||||
// 4. Assign colors
|
||||
ImVec4 *colors = style.Colors;
|
||||
colors[ImGuiCol_Text] = fg;
|
||||
colors[ImGuiCol_WindowBg] = bg;
|
||||
colors[ImGuiCol_Button] = accent;
|
||||
// ... additional color assignments
|
||||
}
|
||||
```
|
||||
|
||||
The RGBA() helper
|
||||
-----------------
|
||||
|
||||
The `RGBA()` function (defined in `themes/ThemeHelpers.h`) converts
|
||||
packed RGB hex values to ImGui's `ImVec4` format:
|
||||
|
||||
```cpp
|
||||
const ImVec4 color = RGBA(0xRRGGBB); // Opaque (alpha = 1.0)
|
||||
const ImVec4 color = RGBA(0xRRGGBB, 0.5f); // With custom alpha
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```cpp
|
||||
const ImVec4 white = RGBA(0xFFFFFF);
|
||||
const ImVec4 black = RGBA(0x000000);
|
||||
const ImVec4 red = RGBA(0xFF0000);
|
||||
const ImVec4 blue = RGBA(0x0000FF);
|
||||
const ImVec4 semi = RGBA(0x808080, 0.5f); // 50% transparent gray
|
||||
```
|
||||
|
||||
ImGui color elements
|
||||
--------------------
|
||||
|
||||
Themes must define colors for ImGui's UI elements. Key `ImGuiCol_*`
|
||||
values:
|
||||
|
||||
### Text
|
||||
|
||||
- `ImGuiCol_Text` — Main text color
|
||||
- `ImGuiCol_TextDisabled` — Disabled/grayed-out text
|
||||
- `ImGuiCol_TextSelectedBg` — Text selection background
|
||||
|
||||
### Windows and backgrounds
|
||||
|
||||
- `ImGuiCol_WindowBg` — Window background
|
||||
- `ImGuiCol_ChildBg` — Child window background
|
||||
- `ImGuiCol_PopupBg` — Popup window background
|
||||
|
||||
### Borders
|
||||
|
||||
- `ImGuiCol_Border` — Border color
|
||||
- `ImGuiCol_BorderShadow` — Border shadow (often transparent)
|
||||
|
||||
### Frames (input fields, etc.)
|
||||
|
||||
- `ImGuiCol_FrameBg` — Frame background (normal state)
|
||||
- `ImGuiCol_FrameBgHovered` — Frame background when hovered
|
||||
- `ImGuiCol_FrameBgActive` — Frame background when active/clicked
|
||||
|
||||
### Title bars
|
||||
|
||||
- `ImGuiCol_TitleBg` — Title bar (unfocused)
|
||||
- `ImGuiCol_TitleBgActive` — Title bar (focused)
|
||||
- `ImGuiCol_TitleBgCollapsed` — Collapsed title bar
|
||||
|
||||
### Interactive elements
|
||||
|
||||
- `ImGuiCol_Button` — Button background
|
||||
- `ImGuiCol_ButtonHovered` — Button when hovered
|
||||
- `ImGuiCol_ButtonActive` — Button when pressed
|
||||
- `ImGuiCol_CheckMark` — Checkmark/radio button indicator
|
||||
- `ImGuiCol_SliderGrab` — Slider grab handle
|
||||
- `ImGuiCol_SliderGrabActive` — Slider grab when dragging
|
||||
|
||||
### Headers and separators
|
||||
|
||||
- `ImGuiCol_Header` — Header (tree nodes, collapsing headers)
|
||||
- `ImGuiCol_HeaderHovered` — Header when hovered
|
||||
- `ImGuiCol_HeaderActive` — Header when clicked
|
||||
- `ImGuiCol_Separator` — Separator line
|
||||
- `ImGuiCol_SeparatorHovered` — Separator when hovered
|
||||
- `ImGuiCol_SeparatorActive` — Separator when dragged
|
||||
|
||||
### Scrollbars
|
||||
|
||||
- `ImGuiCol_ScrollbarBg` — Scrollbar background
|
||||
- `ImGuiCol_ScrollbarGrab` — Scrollbar grab
|
||||
- `ImGuiCol_ScrollbarGrabHovered` — Scrollbar grab when hovered
|
||||
- `ImGuiCol_ScrollbarGrabActive` — Scrollbar grab when dragging
|
||||
|
||||
### Tabs
|
||||
|
||||
- `ImGuiCol_Tab` — Tab (inactive)
|
||||
- `ImGuiCol_TabHovered` — Tab when hovered
|
||||
- `ImGuiCol_TabActive` — Tab (active)
|
||||
- `ImGuiCol_TabUnfocused` — Tab in unfocused window
|
||||
- `ImGuiCol_TabUnfocusedActive` — Active tab in unfocused window
|
||||
|
||||
### Tables
|
||||
|
||||
- `ImGuiCol_TableHeaderBg` — Table header background
|
||||
- `ImGuiCol_TableBorderStrong` — Strong table borders
|
||||
- `ImGuiCol_TableBorderLight` — Light table borders
|
||||
- `ImGuiCol_TableRowBg` — Table row background
|
||||
- `ImGuiCol_TableRowBgAlt` — Alternating table row background
|
||||
|
||||
### Navigation and overlays
|
||||
|
||||
- `ImGuiCol_MenuBarBg` — Menu bar background
|
||||
- `ImGuiCol_ResizeGrip` — Resize grip indicator
|
||||
- `ImGuiCol_ResizeGripHovered` — Resize grip when hovered
|
||||
- `ImGuiCol_ResizeGripActive` — Resize grip when dragging
|
||||
- `ImGuiCol_DragDropTarget` — Drag-and-drop target highlight
|
||||
- `ImGuiCol_NavHighlight` — Navigation highlight
|
||||
- `ImGuiCol_NavWindowingHighlight` — Window navigation highlight
|
||||
- `ImGuiCol_NavWindowingDimBg` — Window navigation dim background
|
||||
- `ImGuiCol_ModalWindowDimBg` — Modal window dim background
|
||||
|
||||
### Plots (graphs)
|
||||
|
||||
- `ImGuiCol_PlotLines` — Plot line color
|
||||
- `ImGuiCol_PlotLinesHovered` — Plot line when hovered
|
||||
- `ImGuiCol_PlotHistogram` — Histogram color
|
||||
- `ImGuiCol_PlotHistogramHovered` — Histogram when hovered
|
||||
|
||||
Style parameters
|
||||
----------------
|
||||
|
||||
In addition to colors, themes can customize style parameters:
|
||||
|
||||
```cpp
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
|
||||
// Padding and spacing
|
||||
style.WindowPadding = ImVec2(8.0f, 8.0f); // Window content padding
|
||||
style.FramePadding = ImVec2(6.0f, 4.0f); // Frame (input fields) padding
|
||||
style.CellPadding = ImVec2(6.0f, 4.0f); // Table cell padding
|
||||
style.ItemSpacing = ImVec2(6.0f, 6.0f); // Space between items
|
||||
style.ItemInnerSpacing = ImVec2(6.0f, 4.0f); // Space within composite items
|
||||
|
||||
// Rounding
|
||||
style.WindowRounding = 4.0f; // Window corner rounding
|
||||
style.FrameRounding = 3.0f; // Frame corner rounding
|
||||
style.PopupRounding = 4.0f; // Popup corner rounding
|
||||
style.GrabRounding = 3.0f; // Grab handle rounding
|
||||
style.TabRounding = 4.0f; // Tab corner rounding
|
||||
|
||||
// Borders
|
||||
style.WindowBorderSize = 1.0f; // Window border width
|
||||
style.FrameBorderSize = 1.0f; // Frame border width
|
||||
|
||||
// Scrollbars
|
||||
style.ScrollbarSize = 14.0f; // Scrollbar width
|
||||
style.GrabMinSize = 10.0f; // Minimum grab handle size
|
||||
```
|
||||
|
||||
Creating a new theme
|
||||
--------------------
|
||||
|
||||
Follow these steps to add a new theme to kte:
|
||||
|
||||
### 1. Create the theme file
|
||||
|
||||
Create a new header file in `themes/` (e.g., `themes/MyTheme.h`):
|
||||
|
||||
```cpp
|
||||
// themes/MyTheme.h — Brief description
|
||||
#pragma once
|
||||
#include "ThemeHelpers.h"
|
||||
|
||||
// Expects to be included from GUITheme.h after <imgui.h> and RGBA() helper
|
||||
|
||||
static void
|
||||
ApplyMyTheme()
|
||||
{
|
||||
// Define your color palette
|
||||
const ImVec4 background = RGBA(0x1e1e1e);
|
||||
const ImVec4 foreground = RGBA(0xd4d4d4);
|
||||
const ImVec4 accent = RGBA(0x007acc);
|
||||
// ... more colors
|
||||
|
||||
ImGuiStyle &style = ImGui::GetStyle();
|
||||
|
||||
// Configure style parameters
|
||||
style.WindowPadding = ImVec2(8.0f, 8.0f);
|
||||
// ... more style settings
|
||||
|
||||
ImVec4 *colors = style.Colors;
|
||||
|
||||
// Assign all required colors
|
||||
colors[ImGuiCol_Text] = foreground;
|
||||
colors[ImGuiCol_WindowBg] = background;
|
||||
// ... assign all other ImGuiCol_* values
|
||||
}
|
||||
```
|
||||
|
||||
Refer to existing themes like `Nord.h` for a complete example of all
|
||||
required color assignments.
|
||||
|
||||
### 2. Add theme to GUITheme.h
|
||||
|
||||
Edit `GUITheme.h` to integrate your theme:
|
||||
|
||||
**a) Add to ThemeId enum:**
|
||||
|
||||
```cpp
|
||||
enum class ThemeId {
|
||||
// ... existing themes
|
||||
MyTheme = 13, // Use next available number
|
||||
};
|
||||
```
|
||||
|
||||
**b) Include your theme header:**
|
||||
|
||||
```cpp
|
||||
// After other theme includes
|
||||
#include "themes/MyTheme.h"
|
||||
```
|
||||
|
||||
**c) Create wrapper class in detail namespace:**
|
||||
|
||||
```cpp
|
||||
namespace detail {
|
||||
// ... existing theme classes
|
||||
|
||||
struct MyThemeWrapper final : Theme {
|
||||
[[nodiscard]] const char *Name() const override
|
||||
{
|
||||
return "mytheme"; // Lowercase canonical name
|
||||
}
|
||||
|
||||
void Apply() const override
|
||||
{
|
||||
ApplyMyTheme();
|
||||
}
|
||||
|
||||
ThemeId Id() override
|
||||
{
|
||||
return ThemeId::MyTheme;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
```
|
||||
|
||||
**d) Register in ThemeRegistry():**
|
||||
|
||||
```cpp
|
||||
static const std::vector<std::unique_ptr<Theme>> &
|
||||
ThemeRegistry()
|
||||
{
|
||||
static std::vector<std::unique_ptr<Theme>> reg;
|
||||
if (reg.empty()) {
|
||||
// Add in alphabetical order by canonical name
|
||||
reg.emplace_back(std::make_unique<detail::AmberTheme>());
|
||||
// ... existing themes
|
||||
reg.emplace_back(std::make_unique<detail::MyThemeWrapper>());
|
||||
// ... remaining themes
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Test your theme
|
||||
|
||||
Rebuild kte and test:
|
||||
|
||||
```bash
|
||||
# Set theme in config
|
||||
echo "theme = mytheme" >> ~/.config/kte/kge.ini
|
||||
|
||||
# Or switch at runtime
|
||||
kge
|
||||
:theme mytheme
|
||||
```
|
||||
|
||||
Light/Dark theme variants
|
||||
--------------------------
|
||||
|
||||
Some themes support both light and dark background modes. To implement
|
||||
this:
|
||||
|
||||
### 1. Create separate functions for each variant
|
||||
|
||||
```cpp
|
||||
// themes/MyTheme.h
|
||||
#pragma once
|
||||
#include "ThemeHelpers.h"
|
||||
|
||||
static void
|
||||
ApplyMyThemeDark()
|
||||
{
|
||||
const ImVec4 bg = RGBA(0x1e1e1e); // Dark background
|
||||
const ImVec4 fg = RGBA(0xd4d4d4); // Light text
|
||||
// ... rest of dark theme
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyMyThemeLight()
|
||||
{
|
||||
const ImVec4 bg = RGBA(0xffffff); // Light background
|
||||
const ImVec4 fg = RGBA(0x1e1e1e); // Dark text
|
||||
// ... rest of light theme
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Check background mode in Apply()
|
||||
|
||||
```cpp
|
||||
// In GUITheme.h wrapper class
|
||||
struct MyThemeWrapper final : Theme {
|
||||
// ... Name() and Id() methods
|
||||
|
||||
void Apply() const override
|
||||
{
|
||||
if (gBackgroundMode == BackgroundMode::Dark)
|
||||
ApplyMyThemeDark();
|
||||
else
|
||||
ApplyMyThemeLight();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
See `Solarized.h`, `Gruvbox.h`, `EInk.h`, or `OldBook.h` for complete
|
||||
examples.
|
||||
|
||||
Updating existing themes
|
||||
------------------------
|
||||
|
||||
To modify an existing theme:
|
||||
|
||||
### 1. Locate the theme file
|
||||
|
||||
Theme files are in `themes/` directory. For example, Nord theme is in
|
||||
`themes/Nord.h`.
|
||||
|
||||
### 2. Modify colors or style
|
||||
|
||||
Edit the `ApplyXxxTheme()` function:
|
||||
|
||||
- Update palette color definitions
|
||||
- Change style parameters
|
||||
- Reassign `ImGuiCol_*` values
|
||||
|
||||
### 3. Rebuild and test
|
||||
|
||||
```bash
|
||||
# Rebuild kte
|
||||
cmake --build build
|
||||
|
||||
# Test changes
|
||||
./build/kge
|
||||
```
|
||||
|
||||
Changes take effect immediately on next launch or theme switch.
|
||||
|
||||
Best practices
|
||||
--------------
|
||||
|
||||
When creating or updating themes:
|
||||
|
||||
1. **Start from an existing theme** — Copy a similar theme as a
|
||||
template (e.g., `Nord.h` for dark themes, `Solarized.h` for
|
||||
light/dark variants)
|
||||
|
||||
2. **Define a complete palette first** — Create all color constants at
|
||||
the top before assigning them
|
||||
|
||||
3. **Assign all colors** — Ensure every `ImGuiCol_*` value is set to
|
||||
avoid inheriting unexpected colors
|
||||
|
||||
4. **Use consistent naming** — Follow existing conventions (e.g.,
|
||||
`nord0`, `base03`, descriptive names)
|
||||
|
||||
5. **Test interactivity** — Verify hover, active, and disabled states
|
||||
for buttons, frames, and other interactive elements
|
||||
|
||||
6. **Consider contrast** — Ensure text is readable against backgrounds;
|
||||
test with different content
|
||||
|
||||
7. **Test transparency** — Use alpha values carefully for overlays, dim
|
||||
backgrounds, and selection highlights
|
||||
|
||||
8. **Match style to theme** — Adjust rounding, padding, and borders to
|
||||
suit the theme's aesthetic (e.g., sharp corners for retro themes,
|
||||
rounded for modern)
|
||||
|
||||
9. **Document inspiration** — Note the color scheme's origin or
|
||||
inspiration in the file header
|
||||
|
||||
10. **Maintain alphabetical order** — When registering in
|
||||
`ThemeRegistry()`, maintain alphabetical order by canonical name
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
### Theme not appearing
|
||||
|
||||
- Check that the theme is registered in `ThemeRegistry()` in
|
||||
alphabetical order
|
||||
- Verify the canonical name matches what you're using in config or
|
||||
commands
|
||||
- Ensure the theme header is included in `GUITheme.h`
|
||||
|
||||
### Colors look wrong
|
||||
|
||||
- Verify hex color values are in 0xRRGGBB format (not 0xBBGGRR)
|
||||
- Check alpha values for semi-transparent elements
|
||||
- Ensure all `ImGuiCol_*` values are assigned
|
||||
|
||||
### Style inconsistent
|
||||
|
||||
- Make sure style parameters are set before color assignments
|
||||
- Check that you're getting `ImGui::GetStyle()` reference correctly
|
||||
- Verify no global style changes are overriding theme settings
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
- ImGui style
|
||||
reference: https://github.com/ocornut/imgui/blob/master/imgui.h
|
||||
- Existing themes in `themes/` directory
|
||||
- Color palette resources: coolors.co, colorhunt.co
|
||||
Reference in New Issue
Block a user