visibility.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from typing import TYPE_CHECKING, Any, Callable
  2. from typing_extensions import Self
  3. from ...binding import BindableProperty, bind, bind_from, bind_to
  4. if TYPE_CHECKING:
  5. from ...element import Element
  6. class Visibility:
  7. visible = BindableProperty(on_change=lambda sender, visible: sender.on_visibility_change(visible))
  8. def __init__(self, **kwargs) -> None:
  9. super().__init__(**kwargs)
  10. self.visible = True
  11. def bind_visibility_to(self,
  12. target_object: Any,
  13. target_name: str = 'visible',
  14. forward: Callable = lambda x: x) -> Self:
  15. """Bind the visibility of this element to the target object's target_name property.
  16. The binding works one way only, from this element to the target.
  17. :param target_object: The object to bind to.
  18. :param target_name: The name of the property to bind to.
  19. :param forward: A function to apply to the value before applying it to the target.
  20. """
  21. bind_to(self, 'visible', target_object, target_name, forward)
  22. return self
  23. def bind_visibility_from(self,
  24. target_object: Any,
  25. target_name: str = 'visible',
  26. backward: Callable = lambda x: x, *,
  27. value: Any = None) -> Self:
  28. """Bind the visibility of this element from the target object's target_name property.
  29. The binding works one way only, from the target to this element.
  30. :param target_object: The object to bind from.
  31. :param target_name: The name of the property to bind from.
  32. :param backward: A function to apply to the value before applying it to this element.
  33. :param value: If specified, the element will be visible only when the target value is equal to this value.
  34. """
  35. if value is not None:
  36. def backward(x): return x == value
  37. bind_from(self, 'visible', target_object, target_name, backward)
  38. return self
  39. def bind_visibility(self,
  40. target_object: Any,
  41. target_name: str = 'visible', *,
  42. forward: Callable = lambda x: x,
  43. backward: Callable = lambda x: x,
  44. value: Any = None) -> Self:
  45. """Bind the visibility of this element to the target object's target_name property.
  46. The binding works both ways, from this element to the target and from the target to this element.
  47. :param target_object: The object to bind to.
  48. :param target_name: The name of the property to bind to.
  49. :param forward: A function to apply to the value before applying it to the target.
  50. :param backward: A function to apply to the value before applying it to this element.
  51. :param value: If specified, the element will be visible only when the target value is equal to this value.
  52. """
  53. if value is not None:
  54. def backward(x): return x == value
  55. bind(self, 'visible', target_object, target_name, forward=forward, backward=backward)
  56. return self
  57. def set_visibility(self, visible: bool) -> None:
  58. """Set the visibility of this element.
  59. :param visible: Whether the element should be visible.
  60. """
  61. self.visible = visible
  62. def on_visibility_change(self: 'Element', visible: str) -> None:
  63. """Called when the visibility of this element changes.
  64. :param visible: Whether the element should be visible.
  65. """
  66. if visible and 'hidden' in self._classes:
  67. self._classes.remove('hidden')
  68. self.update()
  69. if not visible and 'hidden' not in self._classes:
  70. self._classes.append('hidden')
  71. self.update()