v0.1.3 — Centered Teletext frame, added full footer with color band, and finalized header alignment.
This commit is contained in:
parent
64f0e74105
commit
211ebfcd01
22
main.py
22
main.py
|
|
@ -1,13 +1,12 @@
|
|||
# ============================================================
|
||||
# File: /home/stu/Projects/Local REPO/telefact/main.py
|
||||
# File: /telefact/main.py
|
||||
# Description:
|
||||
# Entry point for the Telefact Broadcaster mode.
|
||||
# Initializes the Tkinter window, loads configuration,
|
||||
# and renders the Teletext grid with dynamic header.
|
||||
# and renders the Teletext grid with dynamic header/footer.
|
||||
# ============================================================
|
||||
|
||||
import tkinter as tk
|
||||
|
||||
from src.config_manager import ConfigManager
|
||||
from src.telefact_renderer import TelefactRenderer
|
||||
from src.core.telefact_frame import TelefactFrame
|
||||
|
|
@ -31,34 +30,33 @@ def main():
|
|||
height=config["ScreenHeight"],
|
||||
show_grid=config.get("ShowGrid", False),
|
||||
font_path=config["Font"]["Path"],
|
||||
font_size=config["Font"]["Size"],
|
||||
)
|
||||
|
||||
# --- Prepare frame ---
|
||||
frame = TelefactFrame()
|
||||
|
||||
# --- Initialize header ---
|
||||
# --- Header ---
|
||||
header = TelefactHeader(frame, config)
|
||||
header.render()
|
||||
header.update_time(root, renderer)
|
||||
|
||||
# --- Initialize footer ---
|
||||
footer = TelefactFooter(frame, config)
|
||||
footer.render_test_footer()
|
||||
|
||||
# --- Body & footer test content ---
|
||||
# --- Body content ---
|
||||
formatter = TelefactFormatter(frame)
|
||||
formatter.add_body_line(1, "Welcome to the Telefact Broadcaster base.", align="center", color="white")
|
||||
formatter.add_body_line(3, "Press Q or ESC to exit.", align="center", color="cyan")
|
||||
formatter.set_footer("PAGE 100 TELEFACT", align="center", color="green")
|
||||
|
||||
# --- Render frame ---
|
||||
# --- Footer (replaces old PAGE 100 TELEFACT) ---
|
||||
footer = TelefactFooter(frame, config)
|
||||
footer.set_footer("Telefact: The world at your fingertips", align="left", fg="yellow", bg="blue")
|
||||
|
||||
# --- Render everything ---
|
||||
renderer.render(frame)
|
||||
|
||||
# --- Bind exit keys ---
|
||||
root.bind("<Escape>", lambda e: root.quit())
|
||||
root.bind("q", lambda e: root.quit())
|
||||
|
||||
# --- Start loop ---
|
||||
root.mainloop()
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
BIN
src/core/__pycache__/telefact_footer.cpython-313.pyc
Normal file
BIN
src/core/__pycache__/telefact_footer.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -2,8 +2,7 @@
|
|||
# File: /home/stu/Projects/Local REPO/telefact/src/core/telefact_footer.py
|
||||
# Description:
|
||||
# Dynamic Telefact footer renderer for broadcaster mode.
|
||||
# Draws a single bottom-row text band with background color
|
||||
# and per-page contextual support.
|
||||
# Draws a single bottom-row text band with full background fill.
|
||||
# ============================================================
|
||||
|
||||
from src.core.telefact_frame import TelefactFrame
|
||||
|
|
@ -22,24 +21,24 @@ class TelefactFooter:
|
|||
self.frame = frame
|
||||
self.config = config
|
||||
|
||||
# default colors from global config
|
||||
# Default colors
|
||||
colours = config.get("Colours", {})
|
||||
self.default_bg = colours.get("Footer", "blue")
|
||||
self.default_fg = colours.get("TextPrimary", "white")
|
||||
|
||||
# reserved footer row (last visible line)
|
||||
# Reserved row (bottom row = line 24)
|
||||
self.row = frame.rows - 1
|
||||
|
||||
# --------------------------------------------------------
|
||||
def clear_footer(self, bg: str | None = None):
|
||||
"""Clears the footer line with background fill."""
|
||||
"""Clears the footer row with solid background color."""
|
||||
bg_color = bg or self.default_bg
|
||||
for c in range(self.frame.cols):
|
||||
self.frame.set_cell(c, self.row, " ", self.default_fg, bg_color)
|
||||
|
||||
# --------------------------------------------------------
|
||||
def set_footer(self, text: str, align: str = "left", fg: str | None = None, bg: str | None = None):
|
||||
"""Draw a footer message with color and alignment control."""
|
||||
"""Draw footer message with proper background fill."""
|
||||
fg_color = fg or self.default_fg
|
||||
bg_color = bg or self.default_bg
|
||||
self.clear_footer(bg_color)
|
||||
|
|
@ -47,25 +46,26 @@ class TelefactFooter:
|
|||
text = text.strip()
|
||||
text_len = len(text)
|
||||
|
||||
# --- Alignment handling ---
|
||||
# Alignment
|
||||
if align == "center":
|
||||
start_col = (self.frame.cols - text_len) // 2
|
||||
elif align == "right":
|
||||
start_col = max(self.frame.cols - text_len - 1, 0)
|
||||
else:
|
||||
start_col = 1
|
||||
start_col = 1 # left padding
|
||||
|
||||
# --- Background fill ---
|
||||
for c in range(self.frame.cols):
|
||||
self.frame.set_cell(c, self.row, " ", fg_color, bg_color)
|
||||
|
||||
# --- Text overlay ---
|
||||
# Draw each character with full background
|
||||
for i, ch in enumerate(text):
|
||||
pos = start_col + i
|
||||
if 0 <= pos < self.frame.cols:
|
||||
self.frame.set_cell(pos, self.row, ch, fg_color)
|
||||
self.frame.set_cell(pos, self.row, ch, fg_color, bg_color)
|
||||
|
||||
# --------------------------------------------------------
|
||||
def render_test_footer(self):
|
||||
"""Temporary demo for testing footer display."""
|
||||
self.set_footer("Telefact: The world at your fingertips", align="left", fg="yellow", bg="blue")
|
||||
self.set_footer(
|
||||
"Telefact: The world at your fingertips",
|
||||
align="left",
|
||||
fg="yellow",
|
||||
bg="blue",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# ============================================================
|
||||
# File: /home/stu/Projects/Local REPO/telefact/src/core/telefact_frame.py
|
||||
# File: /telefact/src/core/telefact_frame.py
|
||||
# Description:
|
||||
# Telefact Frame (model)
|
||||
# Defines a 40×24 grid and logical regions for Teletext layout.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# ============================================================
|
||||
# File: /home/stu/Projects/Local REPO/telefact/src/core/telefact_header.py
|
||||
# File: /telefact/src/core/telefact_header.py
|
||||
# Description:
|
||||
# Dynamic Telefact header renderer for broadcaster mode.
|
||||
# Displays page numbers, centered service name block with
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
# ============================================================
|
||||
# File: /home/stu/Projects/Local REPO/telefact/src/telefact_renderer.py
|
||||
# File: /telefact/src/telefact_renderer.py
|
||||
# Description:
|
||||
# Telefact Renderer (Tkinter)
|
||||
# Renders a 40×24 Telefact grid with full foreground/background
|
||||
# colour support, aligned inside a CRT-style safe area margin.
|
||||
# No header/footer bars — layout calibration only.
|
||||
# colour support, perfectly centered inside the window.
|
||||
# ============================================================
|
||||
|
||||
import os
|
||||
|
|
@ -44,20 +43,33 @@ class TelefactRenderer:
|
|||
self.height = height
|
||||
self.show_grid = show_grid
|
||||
|
||||
# Teletext dimensions
|
||||
# Teletext logical dimensions
|
||||
self.cols, self.rows = 40, 24
|
||||
|
||||
# Safe area margins (simulate CRT overscan)
|
||||
self.margin_x = 24
|
||||
self.margin_y = 24
|
||||
self.inner_w = width - self.margin_x * 2
|
||||
self.inner_h = height - self.margin_y * 2
|
||||
# --- Dynamic centered layout ---
|
||||
# Define safe area target margins
|
||||
safe_margin_x = 24
|
||||
safe_margin_y = 24
|
||||
|
||||
# Per-cell dimensions
|
||||
self.cell_w = self.inner_w // self.cols
|
||||
self.cell_h = self.inner_h // self.rows
|
||||
self.w = self.inner_w
|
||||
self.h = self.inner_h
|
||||
# Compute total drawable region
|
||||
self.inner_w = width - safe_margin_x * 2
|
||||
self.inner_h = height - safe_margin_y * 2
|
||||
|
||||
# Compute exact per-cell dimensions (float precision)
|
||||
self.cell_w = self.inner_w / self.cols
|
||||
self.cell_h = self.inner_h / self.rows
|
||||
|
||||
# Compute corrected total grid size (may differ slightly due to float math)
|
||||
total_grid_w = self.cell_w * self.cols
|
||||
total_grid_h = self.cell_h * self.rows
|
||||
|
||||
# --- Center grid on screen ---
|
||||
self.margin_x = (width - total_grid_w) / 2
|
||||
self.margin_y = (height - total_grid_h) / 2
|
||||
|
||||
# Cache total grid extents
|
||||
self.w = total_grid_w
|
||||
self.h = total_grid_h
|
||||
|
||||
# Base colours
|
||||
self.colors = {
|
||||
|
|
@ -101,12 +113,12 @@ class TelefactRenderer:
|
|||
return ("Courier New", font_size, "bold")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
def _gx(self, col: int) -> int:
|
||||
"""Grid X coordinate."""
|
||||
def _gx(self, col: int) -> float:
|
||||
"""Grid X coordinate (precise, centered)."""
|
||||
return self.margin_x + col * self.cell_w
|
||||
|
||||
def _gy(self, row: int) -> int:
|
||||
"""Grid Y coordinate."""
|
||||
def _gy(self, row: int) -> float:
|
||||
"""Grid Y coordinate (precise, centered)."""
|
||||
return self.margin_y + row * self.cell_h
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
|
@ -115,21 +127,18 @@ class TelefactRenderer:
|
|||
x = self._gx(col)
|
||||
y = self._gy(row)
|
||||
|
||||
# Draw background block
|
||||
# Background rectangle
|
||||
self.canvas.create_rectangle(
|
||||
x,
|
||||
y,
|
||||
x + self.cell_w,
|
||||
y + self.cell_h,
|
||||
x, y, x + self.cell_w, y + self.cell_h,
|
||||
fill=PALETTE.get(bg, bg),
|
||||
outline=PALETTE.get(bg, bg),
|
||||
outline=PALETTE.get(bg, bg)
|
||||
)
|
||||
|
||||
# Draw text glyph
|
||||
# Foreground glyph
|
||||
if char.strip():
|
||||
self.canvas.create_text(
|
||||
x + 2,
|
||||
y + self.cell_h // 2,
|
||||
y + self.cell_h / 2,
|
||||
anchor="w",
|
||||
text=char,
|
||||
font=self.font,
|
||||
|
|
@ -138,7 +147,7 @@ class TelefactRenderer:
|
|||
|
||||
# ------------------------------------------------------------------
|
||||
def _draw_grid(self) -> None:
|
||||
"""Optional debug overlay for cell alignment."""
|
||||
"""Optional grid overlay for visual debugging."""
|
||||
for c in range(self.cols + 1):
|
||||
x = self._gx(c)
|
||||
self.canvas.create_line(
|
||||
|
|
@ -152,20 +161,17 @@ class TelefactRenderer:
|
|||
|
||||
# ------------------------------------------------------------------
|
||||
def render(self, frame: TelefactFrame) -> None:
|
||||
"""Renders the full Telefact grid (foreground + background)."""
|
||||
"""Renders the entire 40×24 Telefact grid."""
|
||||
self.canvas.delete("all")
|
||||
|
||||
# Fill background
|
||||
# Fill full canvas background
|
||||
self.canvas.create_rectangle(
|
||||
0,
|
||||
0,
|
||||
self.width,
|
||||
self.height,
|
||||
0, 0, self.width, self.height,
|
||||
fill=PALETTE.get(self.colors["Background"], self.colors["Background"]),
|
||||
width=0,
|
||||
)
|
||||
|
||||
# Draw all cells (bg first, then text)
|
||||
# Draw text grid (each cell: bg + fg)
|
||||
for row in range(frame.rows):
|
||||
for col in range(frame.cols):
|
||||
ch, fg, bg = frame.get_cell(col, row)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user