1
0
python-roguelike/message_log.py

83 lines
2.4 KiB
Python
Raw Normal View History

2022-01-12 13:45:52 -05:00
from typing import Iterable, List, Reversible, Tuple
2022-01-11 16:08:57 -05:00
import textwrap
import tcod
import color
class Message:
def __init__(self, text: str, fg: Tuple[int, int, int]):
self.plain_text = text
self.fg = fg
self.count = 1
@property
def full_text(self) -> str:
"""The full text of this message, including the count if necessary."""
if self.count > 1:
return f"{self.plain_text} (x{self.count})"
2022-01-11 16:08:57 -05:00
return self.plain_text
class MessageLog:
def __init__(self) -> None:
self.messages: List[Message] = []
def add_message(
2022-02-08 10:00:28 -05:00
self, text: str, fg: Tuple[int, int, int] = color.white, *, stack: bool = True
2022-01-11 16:08:57 -05:00
) -> None:
"""Add a message to this log.
`text` is the message text, `fg` is the text color.
If `stack is True then the message can stack with a previous message
of the same text.
"""
if stack and self.messages and text == self.messages[-1].plain_text:
self.messages[-1].count += 1
else:
self.messages.append(Message(text, fg))
def render(
2022-02-08 10:00:28 -05:00
self,
console: tcod.Console,
x: int,
y: int,
width: int,
height: int,
2022-01-11 16:08:57 -05:00
) -> None:
"""Render this log over the given area.
`x`, `y`, `width`, `height` is the rectangular region to render onto
the `console`.
"""
self.render_messages(console, x, y, width, height, self.messages)
@staticmethod
2022-01-12 13:45:52 -05:00
def wrap(string: str, width: int) -> Iterable[str]:
"""Return a wrapped text message."""
for line in string.splitlines(): # Handle newlines in messages.
2022-02-08 10:00:28 -05:00
yield from textwrap.wrap(line, width, expand_tabs=True)
2022-01-12 13:45:52 -05:00
@classmethod
2022-01-11 16:08:57 -05:00
def render_messages(
2022-02-08 10:00:28 -05:00
cls,
console: tcod.Console,
x: int,
y: int,
width: int,
height: int,
messages: Reversible[Message],
2022-01-11 16:08:57 -05:00
) -> None:
"""Render the messages provided.
The `messages` are rendered starting at the last message and working
backwards.
"""
y_offset = height - 1
for message in reversed(messages):
2022-01-12 13:45:52 -05:00
for line in reversed(list(cls.wrap(message.full_text, width))):
2022-01-11 16:08:57 -05:00
console.print(x=x, y=y + y_offset, string=line, fg=message.fg)
y_offset -= 1
if y_offset < 0:
return # No more space to print messages