Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions src/floors/tkinter_floor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
from rooms.room import Room
from rooms.teleport_room import TeleportRoom

from rooms.tkinter import style
from rooms.tkinter.tkinter_room import TkinterRoom
from rooms.tkinter.tkinter_teleport_room import TkinterTeleportRoom
from utils import globals as my_globals
from utils.room_type import RoomType


Expand Down Expand Up @@ -88,9 +90,78 @@ def draw(self) -> None:
Draws the floor with all the rooms on the canvas.
"""
self.stop_drawing()
self._canvas.delete("all")
self._draw_background()
for room in self._tkinter_rooms():
room.draw(self._canvas)
self._draw_teleport_links()

def _draw_background(self) -> None:
"""
Clears the canvas and draws the empty cells of the floor.
"""
palette = style.get_palette()
self._canvas.delete("all")
self._canvas.configure(background=palette.canvas)
for x in range(self._width):
for y in range(self._height):
x0 = x * my_globals.ROOM_WIDTH + style.ROOM_PADDING_X
y0 = y * my_globals.ROOM_HEIGHT + style.ROOM_PADDING_Y
self._canvas.create_rectangle(
x0,
y0,
x0 + my_globals.ROOM_WIDTH - 2 * style.ROOM_PADDING_X,
y0 + my_globals.ROOM_HEIGHT - 2 * style.ROOM_PADDING_Y,
outline=palette.grid,
width=1,
tags=("grid",),
)

def _draw_teleport_links(self) -> None:
"""
Draws a dashed line from every teleport room to its connected room.
"""
rooms_by_id = {room.get_id(): room for room in self._rooms}
for room in self._rooms:
if not isinstance(room, TeleportRoom):
continue
target = rooms_by_id.get(room.get_connected_room_id())
if target is None:
continue
start = self._cell_center(room)
end = self._cell_center(target)
self._canvas.create_line(
*self._room_edge(start, end),
*self._room_edge(end, start),
fill=style.get_palette().teleport_link,
width=2,
dash=(6, 4),
arrow="last",
arrowshape=(10, 12, 5),
tags=("link",),
)

@staticmethod
def _room_edge(center, towards):
"""
Returns the point where a line from the center of a room
towards another point leaves the room.
"""
delta_x = towards[0] - center[0]
delta_y = towards[1] - center[1]
half_width = my_globals.ROOM_WIDTH / 2 - style.ROOM_PADDING_X
half_height = my_globals.ROOM_HEIGHT / 2 - style.ROOM_PADDING_Y
scale = min(
half_width / abs(delta_x) if delta_x else float("inf"),
half_height / abs(delta_y) if delta_y else float("inf"),
)
return center[0] + delta_x * scale, center[1] + delta_y * scale

@staticmethod
def _cell_center(room: Room):
return (
room[0] * my_globals.ROOM_WIDTH + my_globals.ROOM_WIDTH / 2,
room[1] * my_globals.ROOM_HEIGHT + my_globals.ROOM_HEIGHT / 2,
)

def stop_drawing(self) -> None:
"""
Expand All @@ -106,7 +177,7 @@ def draw_step_by_step(self, delay_ms: int = 500) -> None:
@param delay_ms: delay between two rooms in milliseconds
"""
self.stop_drawing()
self._canvas.delete("all")
self._draw_background()
sorted_rooms = sorted(self._tkinter_rooms(), key=lambda r: r.get_id())
self._draw_next_room(sorted_rooms, delay_ms)

Expand All @@ -118,6 +189,7 @@ def _draw_next_room(self, rooms: List[TkinterRoom], delay_ms: int) -> None:
"""
self._after_id = None
if len(rooms) == 0:
self._draw_teleport_links()
return
rooms[0].draw(self._canvas)
self._after_id = self._canvas.after(
Expand Down
10 changes: 10 additions & 0 deletions src/generators/floor_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def __init__(self, output_file_name: str) -> None:
self.current_floor_name = tk.StringVar()
self.current_floor_name.set(output_file_name)
self.current_floor_seed_var = tk.StringVar()
self.position = tk.StringVar()
self.next_seed = tk.StringVar()
self.next_seed.set(secrets.token_hex(16))

Expand All @@ -37,6 +38,7 @@ def add_floor(self, floor: TkinterFloor) -> None:
self.current_floor_index = len(self._floors) - 1
self.current_floor_name.set(floor.name)
self.current_floor_seed_var.set(floor.seed)
self._update_position()

def get_current_floor(self) -> TkinterFloor:
"""
Expand All @@ -63,6 +65,7 @@ def decrease_floor(self) -> None:
self._floors[self.current_floor_index].draw()
self.current_floor_name.set(self._floors[self.current_floor_index].name)
self.current_floor_seed_var.set(self.get_current_floor().seed)
self._update_position()

def increase_floor(self) -> None:
"""
Expand All @@ -76,3 +79,10 @@ def increase_floor(self) -> None:
current_floor.draw()
self.current_floor_name.set(current_floor.name)
self.current_floor_seed_var.set(self.get_current_floor().seed)
self._update_position()

def _update_position(self) -> None:
"""
Updates the text that shows which floor is displayed.
"""
self.position.set(f"Floor {self.current_floor_index + 1} / {len(self._floors)}")
84 changes: 55 additions & 29 deletions src/generators/theme_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,85 @@
Module to handle the theme of the application.
"""

from typing import Callable, Optional
from tkinter import Tk, Canvas, ttk

from rooms.tkinter import style


class ThemeHandler:
"""
Class to handle the theme of the application.
"""

def __init__(self, tk: Tk, canvas: Canvas) -> None:
def __init__(
self, tk: Tk, canvas: Canvas, on_change: Optional[Callable[[], None]] = None
) -> None:
"""
Creates a new theme handler.
@param tk: Root of the application
@param canvas: Canvas of the application
@param on_change: Called after the theme has changed, e.g. to redraw the floor
"""
self._tk = tk
self._canvas = canvas
self._current_theme = "light"
self._on_change = on_change
self._palette = style.LIGHT
self.apply_theme()

def _set_light_theme(self) -> None:
self._tk.configure(background="light gray", highlightbackground="black")
style = ttk.Style(self._tk)
style.configure(
"TButton", background="white", foreground="black", hover="black"
)
style.configure("TFrame", background="light gray", foreground="black")
style.theme_use("default")
self._canvas.configure(background="white", highlightbackground="black")

def _set_dark_theme(self) -> None:
self._tk.configure(background="dark gray", highlightbackground="white")
self._canvas.configure(background="black", highlightbackground="white")
style = ttk.Style(self._tk)
style.configure("TFrame", background="dark gray", foreground="white")
style.configure("TButton", background="black", foreground="white")
# set color on hover
style.map("TButton", background=[("active", "gray")])

def switch_theme(self) -> None:
"""
Switches the theme of the application.
"""
if self._current_theme == "light":
self._current_theme = "dark"
else:
self._current_theme = "light"
self._palette = style.DARK if self._palette is style.LIGHT else style.LIGHT
self.apply_theme()
if self._on_change is not None:
self._on_change()

def apply_theme(self) -> None:
"""
Applies the current theme to the application.
"""
if self._current_theme == "light":
self._set_light_theme()
else:
self._set_dark_theme()
palette = self._palette
style.set_palette(palette)
self._tk.configure(background=palette.window)
self._canvas.configure(
background=palette.canvas, highlightthickness=0, borderwidth=0
)
ttk_style = ttk.Style(self._tk)
ttk_style.theme_use("clam")
ttk_style.configure(
".",
background=palette.panel,
foreground=palette.text,
fieldbackground=palette.entry,
bordercolor=palette.grid,
lightcolor=palette.panel,
darkcolor=palette.panel,
insertcolor=palette.text,
font=("DejaVu Sans", 10),
)
ttk_style.configure("TFrame", background=palette.panel)
ttk_style.configure("TLabel", background=palette.panel, foreground=palette.text)
ttk_style.configure(
"Muted.TLabel", background=palette.panel, foreground=palette.muted_text
)
ttk_style.configure(
"TButton",
background=palette.button,
foreground=palette.text,
bordercolor=palette.grid,
focuscolor=palette.button,
padding=(12, 4),
)
ttk_style.map(
"TButton",
background=[("pressed", palette.grid), ("active", palette.button_active)],
)
ttk_style.configure(
"TEntry",
fieldbackground=palette.entry,
foreground=palette.text,
bordercolor=palette.grid,
padding=(6, 3),
)
Loading
Loading