Skip to content

Commit

Permalink
Add mouse button/mask enums.
Browse files Browse the repository at this point in the history
Continuing to replace loose constants with enums.
  • Loading branch information
HexDecimal committed Jun 19, 2023
1 parent a7372fb commit 8e7dd8b
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 45 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ Changes relevant to the users of python-tcod are documented here.
This project adheres to [Semantic Versioning](https://semver.org/) since version `2.0.0`.

## [Unreleased]
### Added
- Added the enums `tcod.event.MouseButton` and `tcod.event.MouseButtonMask`.

### Changed
- Using `libtcod 1.24.0`.

### Deprecated
- Mouse button and mask constants have been replaced by enums.

### Fixed
- `WindowResized` literal annotations were in the wrong case.

Expand Down
113 changes: 68 additions & 45 deletions tcod/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,46 +240,48 @@ class Modifier(enum.IntFlag):
"""Alt graph."""


# manually define names for SDL macros
BUTTON_LEFT = 1
BUTTON_MIDDLE = 2
BUTTON_RIGHT = 3
BUTTON_X1 = 4
BUTTON_X2 = 5
BUTTON_LMASK = 0x1
BUTTON_MMASK = 0x2
BUTTON_RMASK = 0x4
BUTTON_X1MASK = 0x8
BUTTON_X2MASK = 0x10

# reverse tables are used to get the tcod.event name from the value.
_REVERSE_BUTTON_TABLE = {
BUTTON_LEFT: "BUTTON_LEFT",
BUTTON_MIDDLE: "BUTTON_MIDDLE",
BUTTON_RIGHT: "BUTTON_RIGHT",
BUTTON_X1: "BUTTON_X1",
BUTTON_X2: "BUTTON_X2",
}
class MouseButton(enum.IntEnum):
"""An enum for mouse buttons.
_REVERSE_BUTTON_MASK_TABLE = {
BUTTON_LMASK: "BUTTON_LMASK",
BUTTON_MMASK: "BUTTON_MMASK",
BUTTON_RMASK: "BUTTON_RMASK",
BUTTON_X1MASK: "BUTTON_X1MASK",
BUTTON_X2MASK: "BUTTON_X2MASK",
}
.. versionadded:: Unreleased
"""

LEFT = 1
"""Left mouse button."""
MIDDLE = 2
"""Middle mouse button."""
RIGHT = 3
"""Right mouse button."""
X1 = 4
"""Back mouse button."""
X2 = 5
"""Forward mouse button."""

def __repr__(self) -> str:
return f"{self.__class__.__name__}.{self.name}"

_REVERSE_BUTTON_TABLE_PREFIX = _ConstantsWithPrefix(_REVERSE_BUTTON_TABLE)
_REVERSE_BUTTON_MASK_TABLE_PREFIX = _ConstantsWithPrefix(_REVERSE_BUTTON_MASK_TABLE)

class MouseButtonMask(enum.IntFlag):
"""A mask enum for held mouse buttons.
_REVERSE_MOD_TABLE = tcod.event_constants._REVERSE_MOD_TABLE.copy()
del _REVERSE_MOD_TABLE[KMOD_SHIFT]
del _REVERSE_MOD_TABLE[KMOD_CTRL]
del _REVERSE_MOD_TABLE[KMOD_ALT]
del _REVERSE_MOD_TABLE[KMOD_GUI]
.. versionadded:: Unreleased
"""

_REVERSE_MOD_TABLE_PREFIX = _ConstantsWithPrefix(_REVERSE_MOD_TABLE)
LEFT = 0x1
"""Left mouse button is held."""
MIDDLE = 0x2
"""Middle mouse button is held."""
RIGHT = 0x4
"""Right mouse button is held."""
X1 = 0x8
"""Back mouse button is held."""
X2 = 0x10
"""Forward mouse button is held."""

def __repr__(self) -> str:
if self == 0:
return f"{self.__class__.__name__}(0)"
return "|".join(f"{self.__class__.__name__}.{self.__class__(bit).name}" for bit in self.__class__ if bit & self)


class Event:
Expand Down Expand Up @@ -361,11 +363,11 @@ def from_sdl_event(cls, sdl_event: Any) -> Any:
return self

def __repr__(self) -> str:
return "tcod.event.{}(scancode={!r}, sym={!r}, mod={}{})".format(
return "tcod.event.{}(scancode={!r}, sym={!r}, mod={!r}{})".format(
self.__class__.__name__,
self.scancode,
self.sym,
_describe_bitmask(self.mod, _REVERSE_MOD_TABLE_PREFIX),
self.mod,
", repeat=True" if self.repeat else "",
)

Expand Down Expand Up @@ -446,15 +448,15 @@ def __repr__(self) -> str:
self.__class__.__name__,
tuple(self.position),
tuple(self.tile),
_describe_bitmask(self.state, _REVERSE_BUTTON_MASK_TABLE_PREFIX),
MouseButtonMask(self.state),
)

def __str__(self) -> str:
return ("<%s, position=(x=%i, y=%i), tile=(x=%i, y=%i), state=%s>") % (
super().__str__().strip("<>"),
*self.position,
*self.tile,
_describe_bitmask(self.state, _REVERSE_BUTTON_MASK_TABLE),
MouseButtonMask(self.state),
)


Expand Down Expand Up @@ -552,13 +554,13 @@ def from_sdl_event(cls, sdl_event: Any) -> MouseMotion:
return self

def __repr__(self) -> str:
return ("tcod.event.{}(position={!r}, motion={!r}, tile={!r}, tile_motion={!r}, state={})").format(
return ("tcod.event.{}(position={!r}, motion={!r}, tile={!r}, tile_motion={!r}, state={!r})").format(
self.__class__.__name__,
tuple(self.position),
tuple(self.motion),
tuple(self.tile),
tuple(self.tile_motion),
_describe_bitmask(self.state, _REVERSE_BUTTON_MASK_TABLE_PREFIX),
MouseButtonMask(self.state),
)

def __str__(self) -> str:
Expand Down Expand Up @@ -619,19 +621,19 @@ def from_sdl_event(cls, sdl_event: Any) -> Any:
return self

def __repr__(self) -> str:
return "tcod.event.{}(position={!r}, tile={!r}, button={})".format(
return "tcod.event.{}(position={!r}, tile={!r}, button={!r})".format(
self.__class__.__name__,
tuple(self.position),
tuple(self.tile),
_REVERSE_BUTTON_TABLE_PREFIX[self.button],
MouseButton(self.button),
)

def __str__(self) -> str:
return "<type=%r, position=(x=%i, y=%i), tile=(x=%i, y=%i), button=%s)" % (
return "<type=%r, position=(x=%i, y=%i), tile=(x=%i, y=%i), button=%r)" % (
self.type,
*self.position,
*self.tile,
_REVERSE_BUTTON_TABLE[self.button],
MouseButton(self.button),
)


Expand Down Expand Up @@ -2779,6 +2781,27 @@ def __repr__(self) -> str:

def __getattr__(name: str) -> int:
"""Migrate deprecated access of event constants."""
if name.startswith("BUTTON_"):
replacement = {
"BUTTON_LEFT": MouseButton.LEFT,
"BUTTON_MIDDLE": MouseButton.MIDDLE,
"BUTTON_RIGHT": MouseButton.RIGHT,
"BUTTON_X1": MouseButton.X1,
"BUTTON_X2": MouseButton.X2,
"BUTTON_LMASK": MouseButtonMask.LEFT,
"BUTTON_MMASK": MouseButtonMask.MIDDLE,
"BUTTON_RMASK": MouseButtonMask.RIGHT,
"BUTTON_X1MASK": MouseButtonMask.X1,
"BUTTON_X2MASK": MouseButtonMask.X2,
}[name]
warnings.warn(
"Key constants have been replaced with enums.\n"
f"'tcod.event.{name}' should be replaced with 'tcod.event.{replacement!r}'",
FutureWarning,
stacklevel=2,
)
return replacement

value: int | None = getattr(tcod.event_constants, name, None)
if not value:
msg = f"module {__name__!r} has no attribute {name!r}"
Expand Down
7 changes: 7 additions & 0 deletions tests/test_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ def test_deprecate_key_constants() -> None:
_ = tcod.event.SCANCODE_1


def test_deprecate_mouse_constants() -> None:
with pytest.warns(FutureWarning, match=r"MouseButton.LEFT"):
_ = tcod.event.BUTTON_LEFT
with pytest.warns(FutureWarning, match=r"MouseButtonMask.LEFT"):
_ = tcod.event.BUTTON_LMASK


def test_line_where() -> None:
with pytest.warns():
where = tcod.libtcodpy.line_where(1, 0, 3, 4)
Expand Down

0 comments on commit 8e7dd8b

Please sign in to comment.