Coverage for openhcs/textual_tui/services/window_cache.py: 0.0%
68 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-14 05:57 +0000
1"""
2Window position and size caching service for OpenHCS TUI.
4Provides persistent storage of window positions and sizes across application sessions.
5"""
7import json
8import logging
9from pathlib import Path
10from typing import Dict, Optional, Tuple
11from textual.geometry import Offset, Size
13logger = logging.getLogger(__name__)
16class WindowCache:
17 """Service for caching window positions and sizes."""
19 def __init__(self):
20 """Initialize the window cache service."""
21 # Use the same directory as other OpenHCS data
22 self.cache_dir = Path.home() / ".local" / "share" / "openhcs"
23 self.cache_file = self.cache_dir / "window_cache.json"
24 self._cache_data: Dict[str, Dict[str, Dict[str, int]]] = {}
25 self._load_cache()
27 def _load_cache(self) -> None:
28 """Load cache data from disk."""
29 try:
30 if self.cache_file.exists():
31 with open(self.cache_file, 'r') as f:
32 self._cache_data = json.load(f)
33 logger.debug(f"Loaded window cache from {self.cache_file}")
34 else:
35 self._cache_data = {}
36 logger.debug("No existing window cache found, starting fresh")
37 except Exception as e:
38 logger.warning(f"Failed to load window cache: {e}")
39 self._cache_data = {}
41 def _save_cache(self) -> None:
42 """Save cache data to disk."""
43 try:
44 # Ensure cache directory exists
45 self.cache_dir.mkdir(parents=True, exist_ok=True)
47 with open(self.cache_file, 'w') as f:
48 json.dump(self._cache_data, f, indent=2)
49 logger.debug(f"Saved window cache to {self.cache_file}")
50 except Exception as e:
51 logger.error(f"Failed to save window cache: {e}")
53 def save_window_state(self, window_id: str, position: Offset, size: Size) -> None:
54 """
55 Save window position and size to cache.
57 Args:
58 window_id: Unique window identifier (window button name)
59 position: Window position (Offset with x, y)
60 size: Window size (Size with width, height)
61 """
62 try:
63 self._cache_data[window_id] = {
64 "position": {"x": position.x, "y": position.y},
65 "size": {"width": size.width, "height": size.height}
66 }
67 self._save_cache()
68 logger.debug(f"Cached window state for '{window_id}': pos=({position.x},{position.y}), size=({size.width}x{size.height})")
69 except Exception as e:
70 logger.error(f"Failed to save window state for '{window_id}': {e}")
72 def load_window_state(self, window_id: str) -> Optional[Tuple[Offset, Size]]:
73 """
74 Load window position and size from cache.
76 Args:
77 window_id: Unique window identifier (window button name)
79 Returns:
80 Tuple of (position, size) if cached, None if not found
81 """
82 try:
83 if window_id in self._cache_data:
84 data = self._cache_data[window_id]
85 position = Offset(data["position"]["x"], data["position"]["y"])
86 size = Size(data["size"]["width"], data["size"]["height"])
87 logger.debug(f"Loaded cached window state for '{window_id}': pos=({position.x},{position.y}), size=({size.width}x{size.height})")
88 return position, size
89 else:
90 logger.debug(f"No cached state found for window '{window_id}'")
91 return None
92 except Exception as e:
93 logger.error(f"Failed to load window state for '{window_id}': {e}")
94 return None
96 def clear_window_cache(self, window_id: Optional[str] = None) -> None:
97 """
98 Clear cached window state.
100 Args:
101 window_id: Specific window to clear, or None to clear all
102 """
103 try:
104 if window_id:
105 if window_id in self._cache_data:
106 del self._cache_data[window_id]
107 self._save_cache()
108 logger.debug(f"Cleared cache for window '{window_id}'")
109 else:
110 self._cache_data.clear()
111 self._save_cache()
112 logger.debug("Cleared all window cache data")
113 except Exception as e:
114 logger.error(f"Failed to clear window cache: {e}")
117# Global cache instance
118_window_cache: Optional[WindowCache] = None
121def get_window_cache() -> WindowCache:
122 """Get the global window cache instance."""
123 global _window_cache
124 if _window_cache is None:
125 _window_cache = WindowCache()
126 return _window_cache