Files
mind-reader/src/mind_reader/ui/views/session_view.py
T

221 lines
5.7 KiB
Python

import sys
from dataclasses import dataclass
from enum import Enum, auto
from typing import Optional
import wx
from mind_reader.core import SessionState
def enable_high_dpi_support():
if sys.platform == "win32":
try:
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2)
except Exception:
try:
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
except Exception:
pass
class CardState(Enum):
SETTER_NOT_SET = auto()
SETTER_HIDDEN = auto()
SETTER_REVEALED = auto()
GUESSER_DISABLED = auto()
GUESSER_WAITING = auto()
GUESSER_CORRECT = auto()
GUESSER_WRONG = auto()
class ArrowDirection(Enum):
LEFT = auto()
RIGHT = auto()
@dataclass(frozen=True)
class SetterCardColour:
NOT_SET = wx.Colour(82, 97, 107)
HIDDEN = wx.Colour(201, 214, 223)
REVEALED = wx.Colour(240, 245, 249)
@dataclass(frozen=True)
class GuesserCardColour:
DISABLED = wx.Colour(82, 97, 107)
WAITING = wx.Colour(201, 214, 223)
CORRECT = wx.Colour(76, 175, 80)
WRONG = wx.Colour(229, 115, 115)
@dataclass(frozen=True)
class ArrowSymbol:
LEFT: str = "◀"
RIGHT: str = "▶"
class Card(wx.Panel):
def __init__(self, parent, state: CardState):
super().__init__(parent, style=wx.BORDER_SIMPLE)
self._direction: Optional[ArrowDirection] = None
self._state = state
self._setup()
self._update()
def _setup(self):
self.SetMinSize(wx.Size(35, 35))
self.label = wx.StaticText(self, style=wx.ALIGN_CENTER)
# font = self.label.GetFont()
# font.SetPointSize(6)
# self.label.SetFont(font)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.AddStretchSpacer()
sizer.Add(self.label, 0, wx.ALIGN_CENTER)
sizer.AddStretchSpacer()
self.SetSizer(sizer)
def _update(self):
match self._state:
case CardState.SETTER_NOT_SET:
colour = SetterCardColour.NOT_SET
show_arrow = False
case CardState.SETTER_HIDDEN:
colour = SetterCardColour.HIDDEN
show_arrow = False
case CardState.SETTER_REVEALED:
colour = SetterCardColour.REVEALED
show_arrow = True
case CardState.GUESSER_DISABLED:
colour = GuesserCardColour.DISABLED
show_arrow = False
case CardState.GUESSER_WAITING:
colour = GuesserCardColour.WAITING
show_arrow = False
case CardState.GUESSER_CORRECT:
colour = GuesserCardColour.CORRECT
show_arrow = True
case CardState.GUESSER_WRONG:
colour = GuesserCardColour.WRONG
show_arrow = True
match self._direction:
case ArrowDirection.LEFT:
symbol = ArrowSymbol.LEFT
case ArrowDirection.RIGHT:
symbol = ArrowSymbol.RIGHT
if show_arrow and self._direction:
match self._direction:
case ArrowDirection.LEFT:
symbol = ArrowSymbol.LEFT
case ArrowDirection.RIGHT:
symbol = ArrowSymbol.RIGHT
self.label.SetLabel(symbol)
else:
self.label.SetLabel("")
self.SetBackgroundColour(colour)
self.Layout()
self.Refresh()
def set(
self,
state: CardState,
direction: Optional[ArrowDirection] = None,
) -> None:
self._state = state
self._direction = direction
self._update()
class SessionPanel(wx.Panel):
def __init__(self, parent, sequence_length: int = 20):
super().__init__(parent)
self._sequence_length = sequence_length
self._setter_sequence: list[Card] = []
self._guesser_sequence: list[Card] = []
self._setup()
def _setup(self) -> None:
main_sizer = wx.BoxSizer(wx.VERTICAL)
setter_sizer = wx.BoxSizer(wx.HORIZONTAL)
for _ in range(self._sequence_length):
card = Card(self, CardState.SETTER_NOT_SET)
setter_sizer.Add(card, 0, wx.ALL, 3)
self._setter_sequence.append(card)
guesser_sizer = wx.BoxSizer(wx.HORIZONTAL)
for _ in range(self._sequence_length):
card = Card(self, CardState.GUESSER_DISABLED)
guesser_sizer.Add(card, 0, wx.ALL, 3)
self._guesser_sequence.append(card)
main_sizer.Add(setter_sizer, 0, wx.ALL, 5)
main_sizer.Add(guesser_sizer, 0, wx.ALL, 5)
self.SetSizer(main_sizer)
def update_setter_card(
self,
index: int,
state: CardState,
direction: Optional[ArrowDirection] = None,
) -> None:
self._setter_sequence[index].set(state, direction)
def update_guesser_card(
self,
index: int,
state: CardState,
direction: Optional[ArrowDirection] = None,
) -> None:
self._guesser_sequence[index].set(state, direction)
class TestFrame(wx.Frame):
def __init__(self):
super().__init__(None, title="TestFrame", size=wx.Size(900, 500))
main_panel = SessionPanel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(main_panel, 1, wx.EXPAND)
self.SetSizer(main_sizer)
self.Layout()
main_panel.update_setter_card(
0, CardState.SETTER_REVEALED, ArrowDirection.LEFT
)
main_panel.update_guesser_card(
0, CardState.GUESSER_WRONG, ArrowDirection.RIGHT
)
if __name__ == "__main__":
enable_high_dpi_support()
app = wx.App()
frame = TestFrame()
frame.Show()
app.MainLoop()