v0.1.0 — initial Telefact broadcaster base (frame + renderer)
This commit is contained in:
commit
4dab3c8015
32
main.py
Normal file
32
main.py
Normal 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; that’s 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
0
src/__init__.py
Normal file
BIN
src/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
src/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/telefact_renderer.cpython-313.pyc
Normal file
BIN
src/__pycache__/telefact_renderer.cpython-313.pyc
Normal file
Binary file not shown.
0
src/core/__init__.py
Normal file
0
src/core/__init__.py
Normal file
BIN
src/core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
src/core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
src/core/__pycache__/telefact_frame.cpython-313.pyc
Normal file
BIN
src/core/__pycache__/telefact_frame.cpython-313.pyc
Normal file
Binary file not shown.
0
src/core/telefact_body.py
Normal file
0
src/core/telefact_body.py
Normal file
0
src/core/telefact_footer.py
Normal file
0
src/core/telefact_footer.py
Normal file
0
src/core/telefact_formatter.py
Normal file
0
src/core/telefact_formatter.py
Normal file
42
src/core/telefact_frame.py
Normal file
42
src/core/telefact_frame.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""
|
||||
Telefact Frame (model)
|
||||
- Defines a 40×24 grid and logical regions.
|
||||
- No rendering here—pure 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)
|
||||
0
src/core/telefact_header.py
Normal file
0
src/core/telefact_header.py
Normal file
97
src/telefact_renderer.py
Normal file
97
src/telefact_renderer.py
Normal 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()
|
||||
Loading…
Reference in New Issue
Block a user