129 lines
4.0 KiB
Python
129 lines
4.0 KiB
Python
"""
|
|
Table of Contents overlay sub-application.
|
|
|
|
Simple TOC overlay (deprecated in favor of NavigationOverlay).
|
|
Kept for backward compatibility.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
from typing import TYPE_CHECKING, List, Tuple
|
|
from PIL import Image
|
|
|
|
from .base import OverlaySubApplication
|
|
from ..gesture import GestureResponse, ActionType
|
|
from ..state import OverlayState
|
|
from ..html_generator import generate_toc_overlay
|
|
|
|
if TYPE_CHECKING:
|
|
from ..application import EbookReader
|
|
|
|
|
|
class TOCOverlay(OverlaySubApplication):
|
|
"""
|
|
Simple Table of Contents overlay.
|
|
|
|
NOTE: This is deprecated in favor of NavigationOverlay which provides
|
|
a unified interface for both TOC and bookmarks. Kept for backward compatibility.
|
|
|
|
Features:
|
|
- List of chapters with clickable links
|
|
- Chapter navigation
|
|
"""
|
|
|
|
def __init__(self, reader: 'EbookReader'):
|
|
"""Initialize TOC overlay."""
|
|
super().__init__(reader)
|
|
self._cached_chapters: List[Tuple[str, int]] = []
|
|
|
|
def get_overlay_type(self) -> OverlayState:
|
|
"""Return TOC overlay type."""
|
|
return OverlayState.TOC
|
|
|
|
def open(self, base_page: Image.Image, **kwargs) -> Image.Image:
|
|
"""
|
|
Open the TOC overlay.
|
|
|
|
Args:
|
|
base_page: Current reading page to show underneath
|
|
chapters: List of (chapter_title, chapter_index) tuples
|
|
|
|
Returns:
|
|
Composited image with TOC overlay
|
|
"""
|
|
chapters = kwargs.get('chapters', [])
|
|
|
|
# Store for later use
|
|
self._cached_chapters = chapters
|
|
|
|
# Calculate panel size (60% width, 70% height)
|
|
panel_size = self._calculate_panel_size(0.6, 0.7)
|
|
|
|
# Convert chapters to format expected by HTML generator
|
|
chapter_data = [
|
|
{"index": idx, "title": title}
|
|
for title, idx in chapters
|
|
]
|
|
|
|
# Generate TOC HTML with clickable links
|
|
html = generate_toc_overlay(chapter_data, page_size=panel_size)
|
|
|
|
# Render HTML to image
|
|
overlay_panel = self.render_html_to_image(html, panel_size)
|
|
|
|
# Cache for later use
|
|
self._cached_base_page = base_page.copy()
|
|
self._cached_overlay_image = overlay_panel
|
|
|
|
# Composite and return
|
|
return self.composite_overlay(base_page, overlay_panel)
|
|
|
|
def handle_tap(self, x: int, y: int) -> GestureResponse:
|
|
"""
|
|
Handle tap within TOC overlay.
|
|
|
|
Detects:
|
|
- Chapter selection (chapter:N)
|
|
- Tap outside overlay (closes)
|
|
|
|
Args:
|
|
x, y: Screen coordinates of tap
|
|
|
|
Returns:
|
|
GestureResponse with appropriate action
|
|
"""
|
|
# Query the overlay to see what was tapped
|
|
query_result = self.query_overlay_pixel(x, y)
|
|
|
|
# If query failed (tap outside overlay), close it
|
|
if not query_result:
|
|
return GestureResponse(ActionType.OVERLAY_CLOSED, {})
|
|
|
|
# Check if tapped on a link (chapter)
|
|
if query_result.get("is_interactive") and query_result.get("link_target"):
|
|
link_target = query_result["link_target"]
|
|
|
|
# Parse "chapter:N" format
|
|
if link_target.startswith("chapter:"):
|
|
try:
|
|
chapter_idx = int(link_target.split(":")[1])
|
|
|
|
# Get chapter title for response
|
|
chapter_title = None
|
|
for title, idx in self._cached_chapters:
|
|
if idx == chapter_idx:
|
|
chapter_title = title
|
|
break
|
|
|
|
# Jump to selected chapter
|
|
self.reader.jump_to_chapter(chapter_idx)
|
|
|
|
return GestureResponse(ActionType.CHAPTER_SELECTED, {
|
|
"chapter_index": chapter_idx,
|
|
"chapter_title": chapter_title or f"Chapter {chapter_idx}"
|
|
})
|
|
except (ValueError, IndexError):
|
|
pass
|
|
|
|
# Not a chapter link, close overlay
|
|
return GestureResponse(ActionType.OVERLAY_CLOSED, {})
|