feat(theme): add tone mapping and fix missing palette colors
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Theme Polish & Tone Mapping
|
||||
|
||||
## Problem
|
||||
|
||||
1. **Missing Theme Colors**: The `ThemePalette` dataclass in `src/theme_models.py` only defined a subset of the ~55 ImGui colors. Because `from_dict` strictly matched dataclass fields, colors like `resize_grip` and `tab_dimmed` from the TOML files were being discarded, breaking window resizing handles and inactive tab styling.
|
||||
2. **Context Preview Syntax Palette**: `theme_2.apply()` failed to apply the syntax palette for non-NERV themes, and `src/markdown_helper.py` cached its `TextEditor` instances without clearing them on theme switch. This caused "Context Preview" to remain stuck on the previous theme's syntax colors.
|
||||
3. **Light Theme Brightness**: The user requested a way to dim light themes. We will introduce a Tone Mapping system (Brightness, Contrast, Gamma) that mathematical adjusts the RGB colors before applying them to ImGui. The user requested this to be saved per-palette so each theme can have its own exposure profile.
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
### 1. Fix Theme Models
|
||||
- Ensure `src/theme_models.py`'s `ThemePalette` dataclass has all missing ImGui colors (e.g., `resize_grip`, `resize_grip_active`, `resize_grip_hovered`, `tab_dimmed`, `tab_dimmed_selected`, `docking_preview`, `plot_lines`, `nav_windowing_highlight`, etc.). *(Note: I proactively applied the class definition update during exploration, but will formally commit it)*.
|
||||
|
||||
### 2. Fix Context Preview Syntax Highlight Sync
|
||||
- Update `src/theme_2.py` to ensure `apply_syntax_palette()` is called for *all* themes during `apply()`.
|
||||
- Add an `import src.markdown_helper; src.markdown_helper.get_renderer().clear_cache()` call to the end of `theme_2.apply()` to force code blocks to recreate their `TextEditor` instances with the new palette.
|
||||
|
||||
### 3. Per-Palette Tone Mapping
|
||||
- Add mathematical tone mapping variables to `src/theme_2.py`: `_brightness`, `_contrast`, and `_gamma` (stored as dictionaries keyed by the palette name to allow per-palette saving).
|
||||
- Implement a math function to adjust RGB floats:
|
||||
- Brightness: `c * brightness`
|
||||
- Contrast: `(c - 0.5) * contrast + 0.5`
|
||||
- Gamma: `pow(c, 1.0 / gamma)`
|
||||
- Update the palette application loop in `theme_2.apply()` to pass every color float through this tone mapper before calling `style.set_color_()`.
|
||||
- Update `save_to_config` and `load_from_config` to persist the tone mapping overrides per-palette under `[theme.tone_mapping.<palette>]`.
|
||||
- Add Brightness, Contrast, and Gamma sliders to the Theme panel in `src/gui_2.py`.
|
||||
|
||||
## Implementation Steps
|
||||
1. **Model & Sync Fixes**: Verify `src/theme_models.py` and update `src/theme_2.py`'s `apply()` function to trigger syntax updates and markdown cache clearing.
|
||||
2. **Tone Mapping Logic**: Add the dicts and the math `_tone_map(rgb, palette)` function to `theme_2.py`, wrapping all color assignments.
|
||||
3. **State Persistence**: Update `save_to_config` / `load_from_config` to handle the new per-palette dictionary.
|
||||
4. **UI Integration**: Add the 3 sliders to `_render_theme_panel` in `src/gui_2.py`, complete with a "Reset to Defaults" button for the current palette.
|
||||
5. **Testing**: Run the existing test suite and verify no regressions in config saving.
|
||||
+8
-8
@@ -1,9 +1,9 @@
|
||||
[ai]
|
||||
provider = "minimax"
|
||||
model = "MiniMax-M3"
|
||||
temperature = 0.699999988079071
|
||||
temperature = 0.0
|
||||
top_p = 1.0
|
||||
max_tokens = 99999
|
||||
max_tokens = 999999
|
||||
history_trunc_limit = 900000
|
||||
active_preset = "Basic Do Not"
|
||||
system_prompt = "- **Do not** create shell scripts, README files, or descriptive files unless explicitly instructed.\n- **Do not** do anything beyond what was asked. Suggest extras in text; do not implement them."
|
||||
@@ -16,7 +16,7 @@ paths = [
|
||||
"C:/projects/manual_slop/manual_slop.toml",
|
||||
"C:/projects/Pikuma/ps1-ai/pikuma_ps1.toml",
|
||||
]
|
||||
active = "C:/projects/gencpp/.ai/gencpp_sloppy.toml"
|
||||
active = "C:/projects/Pikuma/ps1-ai/pikuma_ps1.toml"
|
||||
|
||||
[gui]
|
||||
separate_message_panel = true
|
||||
@@ -38,7 +38,7 @@ separate_external_tools = false
|
||||
"AI Settings" = true
|
||||
"MMA Dashboard" = false
|
||||
"Task DAG" = false
|
||||
"Usage Analytics" = false
|
||||
"Usage Analytics" = true
|
||||
"Tier 1" = false
|
||||
"Tier 2" = false
|
||||
"Tier 3" = false
|
||||
@@ -52,17 +52,17 @@ separate_external_tools = false
|
||||
Message = true
|
||||
Response = true
|
||||
"Tool Calls" = true
|
||||
"Text Viewer" = true
|
||||
"Text Viewer" = false
|
||||
Theme = true
|
||||
"Log Management" = true
|
||||
Diagnostics = true
|
||||
Diagnostics = false
|
||||
"Context Preview" = false
|
||||
"External Tools" = false
|
||||
"Shader Editor" = false
|
||||
"Undo/Redo History" = false
|
||||
|
||||
[theme]
|
||||
palette = "Nord Dark"
|
||||
palette = "moss"
|
||||
font_path = "C:/projects/manual_slop/assets/fonts/MapleMono-Regular.ttf"
|
||||
font_size = 20.0
|
||||
scale = 1.0
|
||||
@@ -81,7 +81,7 @@ logs_dir = "C:\\projects\\manual_slop\\logs"
|
||||
scripts_dir = "C:\\projects\\manual_slop\\scripts"
|
||||
|
||||
[rag]
|
||||
enabled = true
|
||||
enabled = false
|
||||
embedding_provider = "local"
|
||||
chunk_size = 1000
|
||||
chunk_overlap = 200
|
||||
|
||||
+27
-23
@@ -44,20 +44,20 @@ Collapsed=0
|
||||
DockId=0x00000010,0
|
||||
|
||||
[Window][Message]
|
||||
Pos=1276,28
|
||||
Size=1495,1608
|
||||
Pos=1196,28
|
||||
Size=1362,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Response]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,5
|
||||
|
||||
[Window][Tool Calls]
|
||||
Pos=1276,28
|
||||
Size=1495,1608
|
||||
Pos=1196,28
|
||||
Size=1362,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000006,3
|
||||
|
||||
@@ -77,7 +77,7 @@ DockId=0xAFC85805,2
|
||||
|
||||
[Window][Theme]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,0
|
||||
|
||||
@@ -87,8 +87,8 @@ Size=900,700
|
||||
Collapsed=0
|
||||
|
||||
[Window][Diagnostics]
|
||||
Pos=1210,28
|
||||
Size=1514,1470
|
||||
Pos=1655,28
|
||||
Size=1658,1838
|
||||
Collapsed=0
|
||||
DockId=0x00000006,4
|
||||
|
||||
@@ -105,26 +105,26 @@ Collapsed=0
|
||||
DockId=0x0000000D,0
|
||||
|
||||
[Window][Discussion Hub]
|
||||
Pos=1276,28
|
||||
Size=1495,1608
|
||||
Pos=1196,28
|
||||
Size=1362,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
|
||||
[Window][Operations Hub]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,4
|
||||
|
||||
[Window][Files & Media]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,2
|
||||
|
||||
[Window][AI Settings]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,3
|
||||
|
||||
@@ -140,8 +140,8 @@ Collapsed=0
|
||||
DockId=0x00000006,2
|
||||
|
||||
[Window][Log Management]
|
||||
Pos=1276,28
|
||||
Size=1495,1608
|
||||
Pos=1196,28
|
||||
Size=1362,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000006,2
|
||||
|
||||
@@ -410,7 +410,7 @@ DockId=0x00000006,1
|
||||
|
||||
[Window][Project Settings]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Size=1194,1548
|
||||
Collapsed=0
|
||||
DockId=0x00000010,1
|
||||
|
||||
@@ -521,10 +521,9 @@ Size=2176,1441
|
||||
Collapsed=0
|
||||
|
||||
[Window][###Text_Viewer_Unified]
|
||||
Pos=0,28
|
||||
Size=1274,1608
|
||||
Pos=182,742
|
||||
Size=1163,908
|
||||
Collapsed=0
|
||||
DockId=0x00000010,6
|
||||
|
||||
[Window][Command Palette##manual_slop]
|
||||
Pos=1295,781
|
||||
@@ -536,6 +535,11 @@ Pos=1626,882
|
||||
Size=638,148
|
||||
Collapsed=0
|
||||
|
||||
[Window][Project Stale]
|
||||
Pos=10,50
|
||||
Size=169,184
|
||||
Collapsed=0
|
||||
|
||||
[Table][0xFB6E3870,4]
|
||||
RefScale=13
|
||||
Column 0 Width=80
|
||||
@@ -825,13 +829,13 @@ Column 4 Weight=1.0000
|
||||
DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y
|
||||
DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A
|
||||
DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02
|
||||
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=2771,1608 Split=X
|
||||
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=2558,1548 Split=X
|
||||
DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2357,1183 Split=X
|
||||
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
|
||||
DockNode ID=0x00000005 Parent=0x0000000B SizeRef=1274,1681 Split=Y Selected=0x3F1379AF
|
||||
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x1DCB2623
|
||||
DockNode ID=0x00000005 Parent=0x0000000B SizeRef=1194,1681 Split=Y Selected=0x3F1379AF
|
||||
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x418C7449
|
||||
DockNode ID=0x00000011 Parent=0x00000005 SizeRef=983,184 Selected=0x432BAE4E
|
||||
DockNode ID=0x00000006 Parent=0x0000000B SizeRef=1495,1681 Selected=0x6F2B5B04
|
||||
DockNode ID=0x00000006 Parent=0x0000000B SizeRef=1362,1681 Selected=0x2C0206CE
|
||||
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
|
||||
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Selected=0x3AEC3498
|
||||
|
||||
|
||||
@@ -4567,6 +4567,27 @@ def render_theme_panel(app: App) -> None:
|
||||
app._flush_to_config()
|
||||
models.save_config(app.config)
|
||||
|
||||
imgui.separator()
|
||||
imgui.text("Tone Mapping (Per-Palette)")
|
||||
curr_p = theme.get_current_palette()
|
||||
|
||||
imgui.text("Brightness")
|
||||
ch_b, b = imgui.slider_float("##tm_b", theme.get_brightness(curr_p), 0.1, 2.0, "%.2f")
|
||||
if ch_b: theme.set_brightness(curr_p, b); app._flush_to_config(); models.save_config(app.config)
|
||||
|
||||
imgui.text("Contrast")
|
||||
ch_c, c = imgui.slider_float("##tm_c", theme.get_contrast(curr_p), 0.1, 2.0, "%.2f")
|
||||
if ch_c: theme.set_contrast(curr_p, c); app._flush_to_config(); models.save_config(app.config)
|
||||
|
||||
imgui.text("Gamma")
|
||||
ch_g, g = imgui.slider_float("##tm_g", theme.get_gamma(curr_p), 0.1, 3.0, "%.2f")
|
||||
if ch_g: theme.set_gamma(curr_p, g); app._flush_to_config(); models.save_config(app.config)
|
||||
|
||||
if imgui.button("Reset Tone Mapping"):
|
||||
theme.reset_tone_mapping(curr_p)
|
||||
app._flush_to_config()
|
||||
models.save_config(app.config)
|
||||
|
||||
imgui.end()
|
||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_theme_panel")
|
||||
|
||||
|
||||
+60
-13
@@ -72,6 +72,38 @@ _current_scale: float = 1.0
|
||||
_transparency: float = 1.0
|
||||
_child_transparency: float = 1.0
|
||||
|
||||
# Per-palette tone mapping: { "Palette Name": value }
|
||||
_brightness: dict[str, float] = {}
|
||||
_contrast: dict[str, float] = {}
|
||||
_gamma: dict[str, float] = {}
|
||||
|
||||
def _get_tm(d: dict[str, float], palette: str, default: float) -> float:
|
||||
return d.get(palette, default)
|
||||
|
||||
def get_brightness(palette: str) -> float: return _get_tm(_brightness, palette, 1.0)
|
||||
def get_contrast(palette: str) -> float: return _get_tm(_contrast, palette, 1.0)
|
||||
def get_gamma(palette: str) -> float: return _get_tm(_gamma, palette, 1.0)
|
||||
|
||||
def set_brightness(palette: str, val: float) -> None: _brightness[palette] = val; apply(palette)
|
||||
def set_contrast(palette: str, val: float) -> None: _contrast[palette] = val; apply(palette)
|
||||
def set_gamma(palette: str, val: float) -> None: _gamma[palette] = val; apply(palette)
|
||||
|
||||
def reset_tone_mapping(palette: str) -> None:
|
||||
for d in [_brightness, _contrast, _gamma]:
|
||||
if palette in d: del d[palette]
|
||||
apply(palette)
|
||||
|
||||
def _tone_map(rgb: tuple[float, float, float, float], palette: str) -> tuple[float, float, float, float]:
|
||||
b, c, g = get_brightness(palette), get_contrast(palette), get_gamma(palette)
|
||||
r, g_val, bl, a = rgb
|
||||
# 1. Brightness
|
||||
r *= b; g_val *= b; bl *= b
|
||||
# 2. Contrast
|
||||
r = (r - 0.5) * c + 0.5; g_val = (g_val - 0.5) * c + 0.5; bl = (bl - 0.5) * c + 0.5
|
||||
# 3. Gamma
|
||||
r = max(0, r)**(1.0/g); g_val = max(0, g_val)**(1.0/g); bl = max(0, bl)**(1.0/g)
|
||||
return (max(0.0, min(1.0, r)), max(0.0, min(1.0, g_val)), max(0.0, min(1.0, bl)), a)
|
||||
|
||||
_crt_filter = CRTFilter()
|
||||
_alert_pulsing = AlertPulsing()
|
||||
_status_flicker = StatusFlicker()
|
||||
@@ -129,7 +161,7 @@ def apply(palette_name: str) -> None:
|
||||
imgui.style_colors_dark()
|
||||
style = imgui.get_style()
|
||||
for col_enum, rgba in colours.items():
|
||||
style.set_color_(col_enum, imgui.ImVec4(*rgba))
|
||||
style.set_color_(col_enum, imgui.ImVec4(*_tone_map(rgba, palette_name)))
|
||||
elif palette_name in _TOML_PALETTES:
|
||||
colours = _TOML_COLOUR_CACHE.get(palette_name, {})
|
||||
if not colours:
|
||||
@@ -139,17 +171,15 @@ def apply(palette_name: str) -> None:
|
||||
imgui.style_colors_dark()
|
||||
style = imgui.get_style()
|
||||
for colenum, rgba in colours.items():
|
||||
style.set_color_(colenum, imgui.ImVec4(*rgba))
|
||||
style.set_color_(colenum, imgui.ImVec4(*_tone_map(rgba, palette_name)))
|
||||
elif hasattr(hello_imgui.ImGuiTheme_, palette_name):
|
||||
theme_enum = getattr(hello_imgui.ImGuiTheme_, palette_name)
|
||||
hello_imgui.apply_theme(theme_enum)
|
||||
# hello_imgui doesn't expose the underlying dict easily to tone-map after-the-fact
|
||||
# without re-reading every enum. For now, BUILTIN and TOML themes get full TM.
|
||||
else:
|
||||
# Fallback to Nord Dark if requested but not found, otherwise ImGui Dark
|
||||
if palette_name == "Nord Dark":
|
||||
# This should not happen since it's in _PALETTES, but for safety
|
||||
imgui.style_colors_dark()
|
||||
else:
|
||||
imgui.style_colors_dark()
|
||||
# Fallback
|
||||
imgui.style_colors_dark()
|
||||
|
||||
# 2. Apply our "Subtle Rounding" professional tweaks on top of ANY theme
|
||||
style = imgui.get_style()
|
||||
@@ -187,6 +217,11 @@ def apply(palette_name: str) -> None:
|
||||
style.anti_aliased_fill = True
|
||||
style.anti_aliased_lines_use_tex = True
|
||||
|
||||
# 3. Sync syntax palette and clear markdown render cache
|
||||
apply_syntax_palette(get_syntax_palette_for_theme(palette_name))
|
||||
import src.markdown_helper
|
||||
src.markdown_helper.get_renderer().clear_cache()
|
||||
|
||||
def set_scale(factor: float) -> None:
|
||||
"""Set the global font/UI scale factor."""
|
||||
global _current_scale
|
||||
@@ -204,16 +239,23 @@ def save_to_config(config: dict) -> None:
|
||||
config["theme"]["scale"] = _current_scale
|
||||
config["theme"]["transparency"] = _transparency
|
||||
config["theme"]["child_transparency"] = _child_transparency
|
||||
sys.stderr.write(f"[DEBUG theme_2] save_to_config: palette={_current_palette}, transparency={_transparency}\n")
|
||||
# Tone mapping
|
||||
tm = {}
|
||||
for p in set(list(_brightness.keys()) + list(_contrast.keys()) + list(_gamma.keys())):
|
||||
tm[p] = {
|
||||
"brightness": _brightness.get(p, 1.0),
|
||||
"contrast": _contrast.get(p, 1.0),
|
||||
"gamma": _gamma.get(p, 1.0)
|
||||
}
|
||||
config["theme"]["tone_mapping"] = tm
|
||||
sys.stderr.write(f"[DEBUG theme_2] save_to_config: palette={_current_palette}\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
def load_from_config(config: dict) -> None:
|
||||
"""Read [theme] from config. Font is handled separately at startup."""
|
||||
import sys
|
||||
global _current_font_path, _current_font_size, _current_scale, _current_palette, _transparency, _child_transparency
|
||||
global _current_font_path, _current_font_size, _current_scale, _current_palette, _transparency, _child_transparency, _brightness, _contrast, _gamma
|
||||
t = config.get("theme", {})
|
||||
sys.stderr.write(f"[DEBUG theme_2] load_from_config raw: {t}\n")
|
||||
sys.stderr.flush()
|
||||
_current_palette = t.get("palette", "10x Dark")
|
||||
if _current_palette in ("", "DPG Default"):
|
||||
_current_palette = "10x Dark"
|
||||
@@ -223,7 +265,12 @@ def load_from_config(config: dict) -> None:
|
||||
_current_scale = float(t.get("scale", 1.0))
|
||||
_transparency = float(t.get("transparency", 1.0))
|
||||
_child_transparency = float(t.get("child_transparency", 1.0))
|
||||
sys.stderr.write(f"[DEBUG theme_2] load_from_config effective: palette={_current_palette}, transparency={_transparency}\n")
|
||||
# Tone mapping
|
||||
tm = t.get("tone_mapping", {})
|
||||
_brightness = {p: float(v.get("brightness", 1.0)) for p, v in tm.items()}
|
||||
_contrast = {p: float(v.get("contrast", 1.0)) for p, v in tm.items()}
|
||||
_gamma = {p: float(v.get("gamma", 1.0)) for p, v in tm.items()}
|
||||
sys.stderr.write(f"[DEBUG theme_2] load_from_config: palette={_current_palette}\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
def apply_current() -> None:
|
||||
|
||||
+33
-3
@@ -9,19 +9,20 @@ from typing import Any
|
||||
VALID_SYNTAX_PALETTES: tuple[str, ...] = ("dark", "light", "mariana", "retro_blue")
|
||||
|
||||
|
||||
@dataclass
|
||||
@dataclass
|
||||
class ThemePalette:
|
||||
window_bg: tuple[int, int, int] = (0, 0, 0)
|
||||
text: tuple[int, int, int] = (200, 200, 200)
|
||||
text_disabled: tuple[int, int, int] = (130, 130, 130)
|
||||
child_bg: tuple[int, int, int] = (0, 0, 0)
|
||||
popup_bg: tuple[int, int, int] = (0, 0, 0)
|
||||
border: tuple[int, int, int] = (60, 60, 60)
|
||||
border_shadow: tuple[int, int, int] = (0, 0, 0)
|
||||
frame_bg: tuple[int, int, int] = (45, 45, 45)
|
||||
frame_bg_hovered: tuple[int, int, int] = (60, 60, 60)
|
||||
frame_bg_active: tuple[int, int, int] = (75, 75, 75)
|
||||
title_bg: tuple[int, int, int] = (40, 40, 40)
|
||||
title_bg_active: tuple[int, int, int] = (60, 45, 15)
|
||||
title_bg_collapsed: tuple[int, int, int] = (30, 30, 30)
|
||||
menu_bar_bg: tuple[int, int, int] = (35, 35, 35)
|
||||
scrollbar_bg: tuple[int, int, int] = (30, 30, 30)
|
||||
scrollbar_grab: tuple[int, int, int] = (80, 80, 80)
|
||||
@@ -39,11 +40,40 @@ class ThemePalette:
|
||||
separator: tuple[int, int, int] = (60, 60, 60)
|
||||
separator_hovered: tuple[int, int, int] = (100, 100, 100)
|
||||
separator_active: tuple[int, int, int] = (200, 200, 200)
|
||||
resize_grip: tuple[int, int, int] = (60, 60, 60)
|
||||
resize_grip_hovered: tuple[int, int, int] = (100, 100, 100)
|
||||
resize_grip_active: tuple[int, int, int] = (200, 200, 200)
|
||||
tab: tuple[int, int, int] = (60, 60, 60)
|
||||
tab_hovered: tuple[int, int, int] = (100, 100, 100)
|
||||
tab_selected: tuple[int, int, int] = (100, 100, 100)
|
||||
tab_dimmed: tuple[int, int, int] = (60, 60, 60)
|
||||
tab_dimmed_selected: tuple[int, int, int] = (100, 100, 100)
|
||||
docking_preview: tuple[int, int, int] = (100, 100, 100)
|
||||
docking_empty_bg: tuple[int, int, int] = (20, 20, 20)
|
||||
text: tuple[int, int, int] = (200, 200, 200)
|
||||
text_disabled: tuple[int, int, int] = (130, 130, 130)
|
||||
text_selected_bg: tuple[int, int, int] = (60, 100, 150)
|
||||
table_header_bg: tuple[int, int, int] = (55, 55, 55)
|
||||
table_border_strong: tuple[int, int, int] = (60, 60, 60)
|
||||
table_border_light: tuple[int, int, int] = (40, 40, 40)
|
||||
table_row_bg: tuple[int, int, int] = (0, 0, 0)
|
||||
table_row_bg_alt: tuple[int, int, int] = (10, 10, 10)
|
||||
nav_cursor: tuple[int, int, int] = (100, 100, 100)
|
||||
nav_windowing_dim_bg: tuple[int, int, int] = (20, 20, 20)
|
||||
nav_windowing_highlight: tuple[int, int, int] = (200, 200, 200)
|
||||
modal_window_dim_bg: tuple[int, int, int] = (10, 10, 10)
|
||||
plot_lines: tuple[int, int, int] = (100, 100, 100)
|
||||
plot_lines_hovered: tuple[int, int, int] = (200, 100, 100)
|
||||
plot_histogram: tuple[int, int, int] = (100, 100, 100)
|
||||
plot_histogram_hovered: tuple[int, int, int] = (200, 100, 100)
|
||||
drag_drop_target: tuple[int, int, int] = (200, 200, 0)
|
||||
drag_drop_target_bg: tuple[int, int, int] = (0, 0, 0)
|
||||
input_text_cursor: tuple[int, int, int] = (200, 200, 200)
|
||||
tab_dimmed_selected_overline: tuple[int, int, int] = (100, 100, 100)
|
||||
tab_selected_overline: tuple[int, int, int] = (100, 100, 100)
|
||||
text_link: tuple[int, int, int] = (60, 100, 150)
|
||||
tree_lines: tuple[int, int, int] = (60, 60, 60)
|
||||
unsaved_marker: tuple[int, int, int] = (200, 200, 200)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> ThemePalette:
|
||||
@@ -122,7 +152,7 @@ def load_theme_file(path: Path, scope: str) -> ThemeFile:
|
||||
raise ValueError(f"failed to parse theme TOML {path}: {e}") from e
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError(f"theme TOML {path} must be a top-level table")
|
||||
name = path.stem
|
||||
name = data.get("name", path.stem)
|
||||
theme = ThemeFile.from_dict(name, data, source_path=path, scope=scope)
|
||||
return theme
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
name = "10x Dark"
|
||||
syntax_palette = "dark"
|
||||
description = "10x Dark Theme"
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
name = "Binks"
|
||||
syntax_palette = "light"
|
||||
description = "Binks Theme"
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
name = "Monokai"
|
||||
syntax_palette = "dark"
|
||||
description = "Monokai Theme"
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
name = "Nord Dark"
|
||||
syntax_palette = "dark"
|
||||
description = "Nord Dark Theme"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user