MIL-002: Step 1 - User interface
Review record RC-024 (Go, autonomous mode, not independent). Task: MIL-002#1 Task: MIL-002#2 Task: MIL-002#3 Task: MIL-002#4
This commit is contained in:
@@ -1,28 +1,44 @@
|
||||
"""Entry point of the flash card program.
|
||||
|
||||
@file app.py
|
||||
@brief Starts the program; the window arrives in MIL-002.
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import NoReturn
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
"""Run the program and return its exit code.
|
||||
|
||||
The window arrives in MIL-002; for now nothing happens.
|
||||
|
||||
@param argv Command line arguments, or None for none.
|
||||
@return The exit code, 0 on success.
|
||||
"""
|
||||
return 0
|
||||
|
||||
|
||||
def run() -> NoReturn:
|
||||
"""Run the program and exit the interpreter with its exit code.
|
||||
|
||||
@return Never returns; the function always raises SystemExit.
|
||||
@throws SystemExit Always, with the exit code of main.
|
||||
"""
|
||||
raise SystemExit(main())
|
||||
"""Entry point and composition root of the flash card program.
|
||||
|
||||
@file app.py
|
||||
@brief Creates the window, its view model and view, and runs the main loop.
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from collections.abc import Sequence
|
||||
from typing import NoReturn
|
||||
|
||||
from flash_card.presentation.features.flash_card.flash_card_view import FlashCardView
|
||||
from flash_card.presentation.features.flash_card.flash_card_view_model import (
|
||||
FlashCardViewModel,
|
||||
)
|
||||
|
||||
|
||||
def create_application() -> tuple[tk.Tk, FlashCardView]:
|
||||
"""Create the root window and the flash card view.
|
||||
|
||||
@return The root window and the view built on it.
|
||||
"""
|
||||
root = tk.Tk()
|
||||
view = FlashCardView(root, FlashCardViewModel())
|
||||
return root, view
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
"""Run the program and return its exit code.
|
||||
|
||||
@param argv Command line arguments, or None for none.
|
||||
@return The exit code, 0 on success.
|
||||
"""
|
||||
root, _view = create_application()
|
||||
root.mainloop()
|
||||
return 0
|
||||
|
||||
|
||||
def run() -> NoReturn:
|
||||
"""Run the program and exit the interpreter with its exit code.
|
||||
|
||||
@return Never returns; the function always raises SystemExit.
|
||||
@throws SystemExit Always, with the exit code of main.
|
||||
"""
|
||||
raise SystemExit(main())
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
"""Features of the presentation layer, one folder each."""
|
||||
@@ -0,0 +1 @@
|
||||
"""The flash card feature: its view and view model."""
|
||||
@@ -0,0 +1,94 @@
|
||||
"""View of the flash card screen.
|
||||
|
||||
@file flash_card_view.py
|
||||
@brief Builds the window of the wireframe: card canvas and two buttons.
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
|
||||
from flash_card.constants import (
|
||||
ASSETS_DIR,
|
||||
BACKGROUND_COLOR,
|
||||
CARD_CENTER_X,
|
||||
CARD_FRONT_IMAGE_NAME,
|
||||
CARD_HEIGHT,
|
||||
CARD_WIDTH,
|
||||
FRONT_TEXT_COLOR,
|
||||
LANGUAGE_FONT,
|
||||
LANGUAGE_TEXT_Y,
|
||||
RIGHT_IMAGE_NAME,
|
||||
WINDOW_PADDING,
|
||||
WINDOW_TITLE,
|
||||
WORD_FONT,
|
||||
WORD_TEXT_Y,
|
||||
WRONG_IMAGE_NAME,
|
||||
)
|
||||
from flash_card.presentation.features.flash_card.flash_card_view_model import (
|
||||
FlashCardViewModel,
|
||||
)
|
||||
|
||||
|
||||
class FlashCardView:
|
||||
"""The flash card window: a card and the wrong and right buttons."""
|
||||
|
||||
def __init__(self, root: tk.Tk, view_model: FlashCardViewModel) -> None:
|
||||
"""Build the window on a root.
|
||||
|
||||
@param root The Tk root window.
|
||||
@param view_model The data to show.
|
||||
"""
|
||||
## @brief The Tk root window.
|
||||
self._root = root
|
||||
## @brief The data source of the texts.
|
||||
self._view_model = view_model
|
||||
root.title(WINDOW_TITLE)
|
||||
root.config(padx=WINDOW_PADDING, pady=WINDOW_PADDING, bg=BACKGROUND_COLOR)
|
||||
|
||||
# Kept as attributes: Tkinter drops an image nothing refers to.
|
||||
## @brief Card front image, kept so Tk does not drop it.
|
||||
self._card_front_image = tk.PhotoImage(file=ASSETS_DIR / CARD_FRONT_IMAGE_NAME)
|
||||
## @brief Wrong button image, kept so Tk does not drop it.
|
||||
self._wrong_image = tk.PhotoImage(file=ASSETS_DIR / WRONG_IMAGE_NAME)
|
||||
## @brief Right button image, kept so Tk does not drop it.
|
||||
self._right_image = tk.PhotoImage(file=ASSETS_DIR / RIGHT_IMAGE_NAME)
|
||||
|
||||
## @brief Canvas that draws the card.
|
||||
self.canvas = tk.Canvas(
|
||||
root,
|
||||
width=CARD_WIDTH,
|
||||
height=CARD_HEIGHT,
|
||||
bg=BACKGROUND_COLOR,
|
||||
highlightthickness=0,
|
||||
)
|
||||
## @brief Canvas item id of the card image.
|
||||
self.image_id = self.canvas.create_image(
|
||||
CARD_CENTER_X, CARD_HEIGHT / 2, image=self._card_front_image
|
||||
)
|
||||
## @brief Canvas item id of the language name text.
|
||||
self.language_text_id = self.canvas.create_text(
|
||||
CARD_CENTER_X,
|
||||
LANGUAGE_TEXT_Y,
|
||||
text=view_model.language_name,
|
||||
font=LANGUAGE_FONT,
|
||||
fill=FRONT_TEXT_COLOR,
|
||||
)
|
||||
## @brief Canvas item id of the word text.
|
||||
self.word_text_id = self.canvas.create_text(
|
||||
CARD_CENTER_X,
|
||||
WORD_TEXT_Y,
|
||||
text=view_model.text,
|
||||
font=WORD_FONT,
|
||||
fill=FRONT_TEXT_COLOR,
|
||||
)
|
||||
self.canvas.grid(row=0, column=0, columnspan=2)
|
||||
|
||||
## @brief Button for a word the user does not know.
|
||||
self.wrong_button = tk.Button(
|
||||
root, image=self._wrong_image, highlightthickness=0, bd=0
|
||||
)
|
||||
self.wrong_button.grid(row=1, column=0)
|
||||
## @brief Button for a word the user knows.
|
||||
self.right_button = tk.Button(
|
||||
root, image=self._right_image, highlightthickness=0, bd=0
|
||||
)
|
||||
self.right_button.grid(row=1, column=1)
|
||||
@@ -0,0 +1,27 @@
|
||||
"""View model of the flash card screen.
|
||||
|
||||
@file flash_card_view_model.py
|
||||
@brief Exposes the texts shown on the card; free of any Tkinter import.
|
||||
"""
|
||||
|
||||
from flash_card.constants import PLACEHOLDER_LANGUAGE_NAME, PLACEHOLDER_WORD
|
||||
|
||||
|
||||
class FlashCardViewModel:
|
||||
"""Data the flash card view shows."""
|
||||
|
||||
@property
|
||||
def language_name(self) -> str:
|
||||
"""Return the language name shown on the card.
|
||||
|
||||
@return The display name of the language.
|
||||
"""
|
||||
return PLACEHOLDER_LANGUAGE_NAME
|
||||
|
||||
@property
|
||||
def text(self) -> str:
|
||||
"""Return the word shown on the card.
|
||||
|
||||
@return The word text.
|
||||
"""
|
||||
return PLACEHOLDER_WORD
|
||||
Reference in New Issue
Block a user