feat(ui): Integrate imgui_markdown and professional fonts for rich text rendering
This commit is contained in:
BIN
assets/fonts/Inter-BoldItalic.ttf
Normal file
BIN
assets/fonts/Inter-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Inter-Italic.ttf
Normal file
BIN
assets/fonts/Inter-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/MapleMono-Bold.ttf
Normal file
BIN
assets/fonts/MapleMono-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/MapleMono-BoldItalic.ttf
Normal file
BIN
assets/fonts/MapleMono-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/MapleMono-Italic.ttf
Normal file
BIN
assets/fonts/MapleMono-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/fontawesome-webfont.ttf
Normal file
BIN
assets/fonts/fontawesome-webfont.ttf
Normal file
Binary file not shown.
@@ -1,12 +1,12 @@
|
||||
# Implementation Plan: Markdown Support & Syntax Highlighting
|
||||
|
||||
## Phase 1: Markdown Integration & Setup
|
||||
- [ ] Task: Research and configure `imgui_markdown` within the existing `imgui-bundle` environment.
|
||||
- [ ] Identify required font assets for Markdown (bold, italic, headers).
|
||||
- [ ] Create a `MarkdownRenderer` wrapper class in `src/markdown_helper.py` to manage styling and callbacks (links, etc.).
|
||||
- [ ] Task: Implement basic Markdown rendering in a test panel.
|
||||
- [ ] Verify that bold, italic, and headers render correctly using the defined theme fonts.
|
||||
- [ ] Task: Conductor - User Manual Verification 'Phase 1: Markdown Integration' (Protocol in workflow.md)
|
||||
- [x] Task: Research and configure `imgui_markdown` within the existing `imgui-bundle` environment.
|
||||
- [x] Identify required font assets for Markdown (bold, italic, headers).
|
||||
- [x] Create a `MarkdownRenderer` wrapper class in `src/markdown_helper.py` to manage styling and callbacks (links, etc.).
|
||||
- [x] Task: Implement basic Markdown rendering in a test panel.
|
||||
- [x] Verify that bold, italic, and headers render correctly using the defined theme fonts.
|
||||
- [x] Task: Conductor - User Manual Verification 'Phase 1: Markdown Integration' (Protocol in workflow.md)
|
||||
|
||||
## Phase 2: Syntax Highlighting Implementation
|
||||
- [ ] Task: Implement syntax highlighting for PowerShell, Python, and JSON/TOML.
|
||||
|
||||
@@ -799,6 +799,7 @@ class AppController:
|
||||
"Tool Calls": False,
|
||||
"Theme": True,
|
||||
"Log Management": False,
|
||||
"Markdown Test": False,
|
||||
}
|
||||
saved = self.config.get("gui", {}).get("show_windows", {})
|
||||
self.show_windows = {k: saved.get(k, v) for k, v in _default_windows.items()}
|
||||
|
||||
36
src/gui_2.py
36
src/gui_2.py
@@ -22,6 +22,7 @@ from src import log_pruner
|
||||
from src import models
|
||||
from src import app_controller
|
||||
from src import mcp_client
|
||||
from src import markdown_helper
|
||||
import re
|
||||
|
||||
from pydantic import BaseModel
|
||||
@@ -520,6 +521,13 @@ class App:
|
||||
if self.show_windows.get("Diagnostics", False):
|
||||
self._render_diagnostics_panel()
|
||||
|
||||
if self.show_windows.get("Markdown Test", False):
|
||||
exp, opened = imgui.begin("Markdown Test", self.show_windows["Markdown Test"])
|
||||
self.show_windows["Markdown Test"] = bool(opened)
|
||||
if exp:
|
||||
self._render_markdown_test()
|
||||
imgui.end()
|
||||
|
||||
self.perf_monitor.end_frame()
|
||||
# ---- Modals / Popups
|
||||
with self._pending_dialog_lock:
|
||||
@@ -1212,6 +1220,29 @@ class App:
|
||||
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_diagnostics_panel")
|
||||
imgui.end()
|
||||
|
||||
def _render_markdown_test(self) -> None:
|
||||
imgui.text("Markdown Test Panel")
|
||||
imgui.separator()
|
||||
md = """
|
||||
# Header 1
|
||||
## Header 2
|
||||
### Header 3
|
||||
This is **bold** text and *italic* text.
|
||||
And ***bold italic*** text.
|
||||
|
||||
* List item 1
|
||||
* List item 2
|
||||
* Sub-item
|
||||
|
||||
[Link to Google](https://google.com)
|
||||
|
||||
```python
|
||||
def hello():
|
||||
print("Markdown works!")
|
||||
```
|
||||
"""
|
||||
markdown_helper.render(md)
|
||||
|
||||
|
||||
def _render_files_panel(self) -> None:
|
||||
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_files_panel")
|
||||
@@ -2154,7 +2185,7 @@ class App:
|
||||
self.bulk_block()
|
||||
# Table
|
||||
flags = imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable | imgui.TableFlags_.scroll_y
|
||||
if imgui.begin_table("ticket_queue_table", 6, flags, imgui.ImVec2(0, 300)):
|
||||
if imgui.begin_table("ticket_queue_table", 7, flags, imgui.ImVec2(0, 300)):
|
||||
imgui.table_setup_column("Select", imgui.TableColumnFlags_.width_fixed, 40)
|
||||
imgui.table_setup_column("ID", imgui.TableColumnFlags_.width_fixed, 80)
|
||||
imgui.table_setup_column("Priority", imgui.TableColumnFlags_.width_fixed, 100)
|
||||
@@ -2858,7 +2889,8 @@ class App:
|
||||
self.runner_params.callbacks.load_additional_fonts = self._load_fonts
|
||||
self.runner_params.callbacks.post_init = self._post_init
|
||||
self._fetch_models(self.current_provider)
|
||||
immapp.run(self.runner_params)
|
||||
md_options = markdown_helper.get_renderer().options
|
||||
immapp.run(self.runner_params, add_ons_params=immapp.AddOnsParams(with_markdown_options=md_options))
|
||||
# On exit
|
||||
self.shutdown()
|
||||
session_logger.close_session()
|
||||
|
||||
56
src/markdown_helper.py
Normal file
56
src/markdown_helper.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# src/markdown_helper.py
|
||||
from __future__ import annotations
|
||||
from imgui_bundle import imgui_md, imgui, immapp
|
||||
import webbrowser
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
class MarkdownRenderer:
|
||||
"""
|
||||
Wrapper for imgui_md to manage styling, callbacks, and specialized rendering
|
||||
(like syntax highlighting integration).
|
||||
"""
|
||||
def __init__(self):
|
||||
self.options = imgui_md.MarkdownOptions()
|
||||
# Use Inter as the base font for Markdown (matches professional theme)
|
||||
# It expects fonts like Inter-Regular.ttf, Inter-Bold.ttf, etc. in the assets folder
|
||||
self.options.font_options.font_base_path = "fonts/Inter"
|
||||
self.options.font_options.regular_size = 16.0
|
||||
|
||||
# Configure callbacks
|
||||
self.options.callbacks.on_open_link = self._on_open_link
|
||||
|
||||
# Note: Syntax highlighting will be integrated in Phase 2
|
||||
|
||||
def _on_open_link(self, url: str) -> None:
|
||||
"""Handle link clicks in Markdown."""
|
||||
# If it's a URL, open in browser
|
||||
if url.startswith("http"):
|
||||
webbrowser.open(url)
|
||||
else:
|
||||
# Handle local files or internal links
|
||||
# For now, just print. Could integrate with app_controller in Phase 4.
|
||||
print(f"Clicked local link: {url}")
|
||||
|
||||
def render(self, text: str) -> None:
|
||||
"""Render Markdown text using imgui_md."""
|
||||
imgui_md.render(text)
|
||||
|
||||
def render_unindented(self, text: str) -> None:
|
||||
"""Render Markdown text with automatic unindentation."""
|
||||
imgui_md.render_unindented(text)
|
||||
|
||||
# Global instance for easy access
|
||||
_renderer: Optional[MarkdownRenderer] = None
|
||||
|
||||
def get_renderer() -> MarkdownRenderer:
|
||||
global _renderer
|
||||
if _renderer is None:
|
||||
_renderer = MarkdownRenderer()
|
||||
return _renderer
|
||||
|
||||
def render(text: str) -> None:
|
||||
get_renderer().render(text)
|
||||
|
||||
def render_unindented(text: str) -> None:
|
||||
get_renderer().render_unindented(text)
|
||||
Reference in New Issue
Block a user