new strategy to draw news manager

This commit is contained in:
Chuck
2025-07-27 13:19:10 -05:00
parent 05d9f7c057
commit 0601a9fda7

View File

@@ -30,7 +30,7 @@ class NewsManager:
self.news_data = {} self.news_data = {}
self.current_headline_index = 0 self.current_headline_index = 0
self.scroll_position = 0 self.scroll_position = 0
self.cached_text_image = None self.scrolling_image = None # Image for pre-rendering
self.cached_text = None self.cached_text = None
self.cache_manager = CacheManager() self.cache_manager = CacheManager()
self.current_headlines = [] self.current_headlines = []
@@ -214,10 +214,34 @@ class NewsManager:
# Calculate text dimensions for perfect scrolling # Calculate text dimensions for perfect scrolling
self.calculate_scroll_dimensions() self.calculate_scroll_dimensions()
self.create_scrolling_image()
self.current_headlines = display_headlines self.current_headlines = display_headlines
logger.debug(f"Prepared {len(display_headlines)} headlines for display") logger.debug(f"Prepared {len(display_headlines)} headlines for display")
def create_scrolling_image(self):
"""Create a pre-rendered image for smooth scrolling."""
if not self.cached_text:
self.scrolling_image = None
return
try:
font = ImageFont.truetype(self.font_path, self.font_size)
except Exception as e:
logger.warning(f"Failed to load custom font for pre-rendering: {e}. Using default.")
font = ImageFont.load_default()
height = self.display_manager.height
width = self.total_scroll_width
self.scrolling_image = Image.new('RGB', (width, height), (0, 0, 0))
draw = ImageDraw.Draw(self.scrolling_image)
text_height = self.font_size
y_pos = (height - text_height) // 2
draw.text((0, y_pos), self.cached_text, font=font, fill=self.text_color)
logger.debug("Pre-rendered scrolling news image created.")
def calculate_scroll_dimensions(self): def calculate_scroll_dimensions(self):
"""Calculate exact dimensions needed for smooth scrolling""" """Calculate exact dimensions needed for smooth scrolling"""
if not self.cached_text: if not self.cached_text:
@@ -309,58 +333,46 @@ class NewsManager:
return (time.time() - self.last_update) > self.update_interval return (time.time() - self.last_update) > self.update_interval
def get_news_display(self) -> Image.Image: def get_news_display(self) -> Image.Image:
"""Generate the scrolling news ticker display""" """Generate the scrolling news ticker display by cropping the pre-rendered image."""
try: try:
if not self.cached_text: if not self.scrolling_image:
logger.debug("No cached text available, showing loading image") logger.debug("No pre-rendered image available, showing loading image.")
return self.create_no_news_image() return self.create_no_news_image()
# Create display image
width = self.display_manager.width width = self.display_manager.width
height = self.display_manager.height height = self.display_manager.height
img = Image.new('RGB', (width, height), (0, 0, 0)) # Use modulo for continuous scrolling
draw = ImageDraw.Draw(img) self.scroll_position = (self.scroll_position + self.scroll_speed) % self.total_scroll_width
# Load font # Crop the visible part of the image
try: x = self.scroll_position
font = ImageFont.truetype(self.font_path, self.font_size) visible_end = x + width
logger.debug(f"Successfully loaded custom font: {self.font_path}")
except Exception as e:
logger.warning(f"Failed to load custom font '{self.font_path}': {e}. Using default font.")
font = ImageFont.load_default()
# Calculate vertical position (center the text) if visible_end <= self.total_scroll_width:
text_height = self.font_size # No wrap-around needed
y_pos = (height - text_height) // 2 img = self.scrolling_image.crop((x, 0, visible_end, height))
else:
# Handle wrap-around
img = Image.new('RGB', (width, height))
# Calculate scroll position for smooth animation width1 = self.total_scroll_width - x
if self.total_scroll_width > 0: portion1 = self.scrolling_image.crop((x, 0, self.total_scroll_width, height))
# Use modulo for continuous scrolling like stock ticker img.paste(portion1, (0, 0))
self.scroll_position = (self.scroll_position + self.scroll_speed) % self.total_scroll_width
# Scroll from right to left width2 = width - width1
x_pos = width - self.scroll_position portion2 = self.scrolling_image.crop((0, 0, width2, height))
img.paste(portion2, (width1, 0))
# Draw the text # Check for rotation when scroll completes a cycle
draw.text((x_pos, y_pos), self.cached_text, font=font, fill=self.text_color) if self.scroll_position < self.scroll_speed: # Check if we just wrapped around
self.rotation_count += 1
# If text has scrolled partially off screen, draw it again for seamless loop if (self.rotation_enabled and
if x_pos + self.total_scroll_width < width: self.rotation_count >= self.rotation_threshold and
draw.text((x_pos + self.total_scroll_width, y_pos), self.cached_text, font=font, fill=self.text_color) any(len(headlines) > self.headlines_per_feed for headlines in self.news_data.values())):
logger.info("News rotation threshold reached. Preparing new headlines.")
# Check if we should rotate headlines (when scroll wraps around) self.prepare_headlines_for_display()
if self.scroll_position == 0: self.rotation_count = 0
self.rotation_count += 1
# Check if we should rotate headlines
if (self.rotation_enabled and
self.rotation_count >= self.rotation_threshold and
any(len(headlines) > self.headlines_per_feed for headlines in self.news_data.values())):
self.prepare_headlines_for_display()
self.rotation_count = 0
# Remove the delay - let the display controller timing control the speed
return img return img
@@ -432,13 +444,16 @@ class NewsManager:
finally: finally:
self.is_fetching = False self.is_fetching = False
# Get the current news display image (this updates scroll position) # Get the current news display image
img = self.get_news_display() img = self.get_news_display()
# Set the image and update display # Set the image and update display
self.display_manager.image = img self.display_manager.image = img
self.display_manager.update_display() self.display_manager.update_display()
# Add scroll delay to control speed
time.sleep(self.scroll_delay)
# Debug: log scroll position # Debug: log scroll position
if hasattr(self, 'scroll_position') and hasattr(self, 'total_scroll_width'): if hasattr(self, 'scroll_position') and hasattr(self, 'total_scroll_width'):
logger.debug(f"Scroll position: {self.scroll_position}/{self.total_scroll_width}") logger.debug(f"Scroll position: {self.scroll_position}/{self.total_scroll_width}")