v0.1.0 — initial Telefact broadcaster base (frame + renderer)

This commit is contained in:
Stu Leak 2025-11-03 10:06:20 -05:00
commit 4dab3c8015
13 changed files with 171 additions and 0 deletions

32
main.py Normal file
View File

@ -0,0 +1,32 @@
"""
Telefact minimal runner
- Opens a 4:3 800×600 window
- Renders header (blue band) and footer (red band)
- No formatter yet; thats next.
"""
import tkinter as tk
from src.telefact_renderer import TelefactRenderer
from src.core.telefact_frame import TelefactFrame
def main():
root = tk.Tk()
root.title("Telefact — Broadcaster Prototype")
renderer = TelefactRenderer(root, width=800, height=600, show_grid=False)
frame = TelefactFrame()
# put a couple test glyphs so you can confirm alignment quickly
for i, ch in enumerate("TELEFACT"):
frame.set_cell(2 + i, 2, ch, "yellow")
for i, ch in enumerate("BROADCASTER BASE"):
frame.set_cell(2 + i, 4, ch, "white")
renderer.render(frame)
root.bind("<Escape>", lambda e: root.quit())
root.bind("q", lambda e: root.quit())
root.mainloop()
if __name__ == "__main__":
main()

0
src/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

0
src/core/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

View File

View File

View File

View File

@ -0,0 +1,42 @@
"""
Telefact Frame (model)
- Defines a 40×24 grid and logical regions.
- No rendering herepure data model.
"""
class TelefactFrame:
def __init__(self, cols: int = 40, rows: int = 24):
self.cols = cols
self.rows = rows
self.header_rows = 1
self.footer_rows = 1
self.body_rows = self.rows - (self.header_rows + self.footer_rows)
# grid[row][col] -> (char, color_name)
self.grid = [[(" ", "white") for _ in range(self.cols)] for _ in range(self.rows)]
# basic cell ops
def set_cell(self, col: int, row: int, char: str, color: str = "white"):
if 0 <= col < self.cols and 0 <= row < self.rows and char:
self.grid[row][col] = (char[0], color)
def get_cell(self, col: int, row: int):
if 0 <= col < self.cols and 0 <= row < self.rows:
return self.grid[row][col]
return (" ", "white")
def clear(self, char: str = " ", color: str = "white"):
for r in range(self.rows):
for c in range(self.cols):
self.grid[r][c] = (char, color)
# regions
def header_region(self):
return range(0, self.header_rows)
def body_region(self):
return range(self.header_rows, self.header_rows + self.body_rows)
def footer_region(self):
return range(self.rows - self.footer_rows, self.rows)

View File

97
src/telefact_renderer.py Normal file
View File

@ -0,0 +1,97 @@
"""
Telefact Renderer (Tkinter)
- Renders a TelefactFrame to a Canvas.
- Pure Python (stdlib only).
"""
import tkinter as tk
from typing import Dict
from src.core.telefact_frame import TelefactFrame
PALETTE: Dict[str, str] = {
"black": "#000000",
"blue": "#0000FF",
"red": "#FF0000",
"magenta":"#FF00FF",
"green": "#00FF00",
"cyan": "#00FFFF",
"yellow": "#FFFF00",
"white": "#FFFFFF",
}
class TelefactRenderer:
def __init__(self, root: tk.Tk, width: int = 800, height: int = 600, show_grid: bool = False):
self.root = root
self.width = width
self.height = height
self.show_grid = show_grid
# 40×24 grid for Telefact pages
self.cols, self.rows = 40, 24
self.cell_w = max(1, width // self.cols)
self.cell_h = max(1, height // self.rows)
self.w = self.cell_w * self.cols
self.h = self.cell_h * self.rows
self.canvas = tk.Canvas(
root, width=self.w, height=self.h,
highlightthickness=0, bg=PALETTE["black"]
)
self.canvas.pack()
# simple monospace font; will swap for Teletext font later
self.font = ("Courier New", max(12, self.cell_h - 9), "bold")
# ----- low-level drawing helpers -----
def _gx(self, col: int) -> int:
return col * self.cell_w
def _gy(self, row: int) -> int:
return row * self.cell_h
def _fill_row(self, row: int, color: str) -> None:
self.canvas.create_rectangle(
self._gx(0), self._gy(row), self._gx(self.cols), self._gy(row + 1),
fill=PALETTE.get(color, color), width=0
)
def _draw_char(self, col: int, row: int, char: str, color: str) -> None:
x = self._gx(col) + 2
y = self._gy(row) + self.cell_h // 2
self.canvas.create_text(
x, y, anchor="w", text=char,
font=self.font, fill=PALETTE.get(color, color)
)
def _draw_grid(self) -> None:
for c in range(self.cols + 1):
x = self._gx(c)
self.canvas.create_line(x, 0, x, self.h, fill="#202020")
for r in range(self.rows + 1):
y = self._gy(r)
self.canvas.create_line(0, y, self.w, y, fill="#202020")
# ----- public API -----
def render(self, frame: TelefactFrame) -> None:
"""Paint the whole frame to the canvas."""
self.canvas.delete("all")
# background
self.canvas.create_rectangle(0, 0, self.w, self.h,
fill=PALETTE["black"], width=0)
# header/footer colour bands
for r in frame.header_region():
self._fill_row(r, "blue")
for r in frame.footer_region():
self._fill_row(r, "red")
# draw text cells
for row in range(frame.rows):
for col in range(frame.cols):
ch, fg = frame.grid[row][col]
if ch.strip():
self._draw_char(col, row, ch, fg)
if self.show_grid:
self._draw_grid()