# Copyright (C) 2020 by ÿnérant, eichhornchen, nicomarg, charlse # SPDX-License-Identifier: GPL-3.0-or-later import curses from random import randint from typing import List from squirrelbattle.menus import Menu, MainMenu from .display import Box, Display from ..enums import KeyValues, GameMode from ..game import Game from ..resources import ResourceManager from ..translations import gettext as _ class MenuDisplay(Display): """ A class to display the menu objects. """ position: int def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.menubox = Box(*args, **kwargs) def update_menu(self, menu: Menu) -> None: self.menu = menu # Menu values are printed in pad self.pad = self.newpad(self.trueheight, self.truewidth + 2) def update_pad(self) -> None: for i in range(self.trueheight): self.addstr(self.pad, i, 0, " " + self.values[i]) # set a marker on the selected line self.addstr(self.pad, self.menu.position, 0, " >") def display(self) -> None: cornery = 0 if self.height - 2 >= self.menu.position - 1 \ else self.trueheight - self.height + 2 \ if self.height - 2 >= self.trueheight - self.menu.position else 0 # Menu box self.menubox.refresh(self.y, self.x, self.height, self.width) self.pad.erase() self.update_pad() self.refresh_pad(self.pad, cornery, 0, self.y + 1, self.x + 1, self.height - 2 + self.y, self.width - 2 + self.x) def handle_click(self, y: int, x: int, game: Game) -> None: """ We can select a menu item with the mouse. """ self.menu.position = max(0, min(len(self.menu.values) - 1, y - 1)) game.handle_key_pressed(KeyValues.ENTER) @property def truewidth(self) -> int: return max([len(str(a)) for a in self.values]) @property def trueheight(self) -> int: return len(self.values) @property def preferred_width(self) -> int: return self.truewidth + 6 @property def preferred_height(self) -> int: return self.trueheight + 2 @property def values(self) -> List[str]: return [str(a) for a in self.menu.values] class SettingsMenuDisplay(MenuDisplay): """ A class to display specifically a settingsmenu object. """ @property def values(self) -> List[str]: return [_(a[1][1]) + (" : " + ("?" if self.menu.waiting_for_key and a == self.menu.validate() else a[1][0] .replace("\n", "\\n")) if a[1][0] else "") for a in self.menu.values] class MainMenuDisplay(Display): """ A class to display specifically a mainmenu object. """ def __init__(self, menu: MainMenu, *args): super().__init__(*args) self.menu = menu with open(ResourceManager.get_asset_path("ascii_art.txt"), "r") as file: self.title = file.read().split("\n") self.pad = self.newpad(max(self.rows, len(self.title) + 30), max(len(self.title[0]) + 5, self.cols)) self.fg_color = curses.COLOR_WHITE self.menudisplay = MenuDisplay(self.screen, self.pack) self.menudisplay.update_menu(self.menu) def display(self) -> None: for i in range(len(self.title)): self.addstr(self.pad, 4 + i, max(self.width // 2 - len(self.title[0]) // 2 - 1, 0), self.title[i], self.fg_color) msg = _("Credits") self.addstr(self.pad, self.height - 1, self.width - 1 - len(msg), msg) self.refresh_pad(self.pad, 0, 0, self.y, self.x, self.height + self.y - 1, self.width + self.x - 1) menuwidth = min(self.menudisplay.preferred_width, self.width) menuy, menux = len(self.title) + 8, self.width // 2 - menuwidth // 2 - 1 self.menudisplay.refresh( menuy, menux, min(self.menudisplay.preferred_height, self.height - menuy), menuwidth) def handle_click(self, y: int, x: int, game: Game) -> None: menuwidth = min(self.menudisplay.preferred_width, self.width) menuy, menux = len(self.title) + 8, self.width // 2 - menuwidth // 2 - 1 menuheight = min(self.menudisplay.preferred_height, self.height - menuy) if menuy <= y < menuy + menuheight and menux <= x < menux + menuwidth: self.menudisplay.handle_click(y - menuy, x - menux, game) if y <= len(self.title): self.fg_color = randint(0, 1000), randint(0, 1000), randint(0, 1000) if y == self.height - 1 and x >= self.width - 1 - len(_("Credits")): game.state = GameMode.CREDITS class PlayerInventoryDisplay(MenuDisplay): """ A class to handle the display of the player's inventory. """ def update_pad(self) -> None: self.menubox.update_title(_("INVENTORY")) for i, item in enumerate(self.menu.values): rep = self.pack[item.name.upper()] selection = f"[{rep}]" if i == self.menu.position else f" {rep} " self.addstr(self.pad, i + 1, 0, selection + " " + item.translated_name.capitalize()) @property def truewidth(self) -> int: return max(1, self.height if hasattr(self, "height") else 10) @property def trueheight(self) -> int: return 2 + super().trueheight def handle_click(self, y: int, x: int, game: Game) -> None: """ We can select a menu item with the mouse. """ self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2)) game.handle_key_pressed(KeyValues.ENTER) class StoreInventoryDisplay(MenuDisplay): """ A class to handle the display of a merchant's inventory. """ def update_pad(self) -> None: self.menubox.update_title(_("STALL")) for i, item in enumerate(self.menu.values): rep = self.pack[item.name.upper()] selection = f"[{rep}]" if i == self.menu.position else f" {rep} " self.addstr(self.pad, i + 1, 0, selection + " " + item.translated_name.capitalize() + ": " + str(item.price) + " Hazels") @property def truewidth(self) -> int: return max(1, self.height if hasattr(self, "height") else 10) @property def trueheight(self) -> int: return 2 + super().trueheight def handle_click(self, y: int, x: int, game: Game) -> None: """ We can select a menu item with the mouse. """ self.menu.position = max(0, min(len(self.menu.values) - 1, y - 2)) game.handle_key_pressed(KeyValues.ENTER)