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
1 change: 1 addition & 0 deletions doc/changelog.d/228.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
feat: Add dark mode when background is dark
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@

_HAS_TRAME = importlib.util.find_spec("pyvista.trame") and importlib.util.find_spec("trame.app")

DARK_MODE_THRESHOLD = 120

if TYPE_CHECKING:
import numpy as np

Expand Down Expand Up @@ -179,25 +181,31 @@ def scene(self) -> pv.Plotter:
"""PyVista scene."""
return self._pl.scene

def enable_widgets(self):
"""Enable the widgets for the plotter."""
def enable_widgets(self, dark_mode: bool = False) -> None:
"""Enable the widgets for the plotter.

Parameters
----------
dark_mode : bool, default: False
Whether to use dark mode for the widgets.
"""
# Create Plotter widgets
if self._enable_widgets:
self._widgets: List[PlotterWidget] = []
self._widgets.append(Ruler(self._pl._scene))
self._widgets.append(Ruler(self._pl._scene, dark_mode))
[
self._widgets.append(DisplacementArrow(self._pl._scene, direction=dir))
self._widgets.append(DisplacementArrow(self._pl._scene, dir, dark_mode))
for dir in CameraPanDirection
]
[
self._widgets.append(ViewButton(self._pl._scene, direction=dir))
self._widgets.append(ViewButton(self._pl._scene, dir, dark_mode))
for dir in ViewDirection
]
self._widgets.append(MeasureWidget(self))
self._widgets.append(ScreenshotButton(self))
self._widgets.append(MeasureWidget(self, dark_mode))
self._widgets.append(ScreenshotButton(self, dark_mode))
if not self._use_qt:
self._widgets.append(MeshSliderWidget(self))
self._widgets.append(HideButton(self))
self._widgets.append(MeshSliderWidget(self, dark_mode))
self._widgets.append(HideButton(self, dark_mode))

def add_widget(self, widget: Union[PlotterWidget, List[PlotterWidget]]):
"""Add one or more custom widgets to the plotter.
Expand Down Expand Up @@ -403,6 +411,7 @@ def show(
screenshot: Optional[str] = None,
view_2d: Dict = None,
name_filter: str = None,
dark_mode: bool = False,
**plotting_options,
) -> List[Any]:
"""Plot and show any PyAnsys object.
Expand All @@ -420,6 +429,8 @@ def show(
Dictionary with the plane and the viewup vectors of the 2D plane.
name_filter : str, default: None
Regular expression with the desired name or names to include in the plotter.
dark_mode : bool, default: False
Whether to use dark mode for the widgets.
**plotting_options : dict, default: None
Keyword arguments. For allowable keyword arguments, see the
:meth:`Plotter.add_mesh <pyvista.Plotter.add_mesh>` method.
Expand All @@ -446,7 +457,16 @@ def show(
)
# Enable widgets and picking capabilities
if screenshot is None and not ansys.tools.visualization_interface.DOCUMENTATION_BUILD:
self.enable_widgets()
if dark_mode:
self.enable_widgets(dark_mode=dark_mode)
elif all([
color < DARK_MODE_THRESHOLD
for color in self._pl.scene.background_color.int_rgb
]):
print([color for color in self._pl.scene.background_color.int_rgb])
self.enable_widgets(dark_mode=True)
else:
self.enable_widgets()

if self._allow_picking:
self.enable_picking()
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ class Button(PlotterWidget):
Plotter to draw the buttons on.
button_config : tuple
Tuple containing the position and the path to the icon of the button.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter: Plotter, button_config: tuple):
def __init__(self, plotter: Plotter, button_config: tuple, dark_mode: bool = False) -> None:
"""Initialize the ``Button`` class."""
super().__init__(plotter)
self._dark_mode = dark_mode
self._button: vtkButtonWidget = self.plotter.add_checkbox_button_widget(
self.callback, position=button_config.value[2], size=30, border_size=3
)
Expand All @@ -68,9 +71,13 @@ def callback(self, state: bool) -> None:

def update(self) -> None:
"""Assign the image that represents the button."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""
button_repr = self._button.GetRepresentation()
button_icon_path = Path(
Path(__file__).parent / "_images", self.button_config.value[1]
Path(__file__).parent / "_images", f"{self.button_config.value[1]}{is_inv}.png"
)
button_icon = vtkPNGReader()
button_icon.SetFileName(button_icon_path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
class CameraPanDirection(Enum):
"""Provides an enum with the available movement directions of the camera."""

XUP = 0, "upxarrow.png", (5, 170)
XDOWN = 1, "downarrow.png", (5, 130)
YUP = 2, "upyarrow.png", (35, 170)
YDOWN = 3, "downarrow.png", (35, 130)
ZUP = 4, "upzarrow.png", (65, 170)
ZDOWN = 5, "downarrow.png", (65, 130)
XUP = 0, "upxarrow", (5, 170)
XDOWN = 1, "downarrow", (5, 130)
YUP = 2, "upyarrow", (35, 170)
YDOWN = 3, "downarrow", (35, 130)
ZUP = 4, "upzarrow", (65, 170)
ZDOWN = 5, "downarrow", (65, 130)


class DisplacementArrow(Button):
Expand All @@ -47,12 +47,13 @@ class DisplacementArrow(Button):
Plotter to draw the buttons on.
direction : CameraPanDirection
Direction that the camera is to move.

dark_mode : bool, optional
Whether to activate the dark mode or not.
"""

def __init__(self, plotter: Plotter, direction: CameraPanDirection):
def __init__(self, plotter: Plotter, direction: CameraPanDirection, dark_mode: bool = False) -> None:
"""Initialize the ``DisplacementArrow`` class."""
super().__init__(plotter, direction)
super().__init__(plotter, direction, dark_mode)
self.direction = direction
self.update()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ class HideButton(PlotterWidget):
----------
plotter_helper : PlotterHelper
Plotter to add the hide widget to.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter: "Plotter") -> None:
def __init__(self, plotter: "Plotter", dark_mode: bool = False) -> None:
"""Initialize the ``HideButton`` class."""
# Call PlotterWidget ctor
super().__init__(plotter._pl.scene)

self._dark_mode = dark_mode
# Initialize variables
self._actor: vtkActor = None
self._plotter = plotter
Expand All @@ -70,17 +72,22 @@ def callback(self, state: bool) -> None:
widget._button.GetRepresentation().SetVisibility(0)
else:
for widget in self.plotter._widgets:
widget._button.On()
widget._button.GetRepresentation().SetVisibility(1)
widget._button.On()
widget._button.GetRepresentation().SetVisibility(1)

def update(self) -> None:
"""Define the hide widget button parameters."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""

show_vr = self._button.GetRepresentation()
show_vison_icon_file = Path(
Path(__file__).parent / "_images"/ "visibilityon.png"
Path(__file__).parent / "_images" / f"visibilityon{is_inv}.png"
)
show_visoff_icon_file = Path(
Path(__file__).parent / "_images"/ "visibilityoff.png"
Path(__file__).parent / "_images" / f"visibilityon{is_inv}.png"
)
show_r_on = vtkPNGReader()
show_r_on.SetFileName(show_vison_icon_file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ class MeasureWidget(PlotterWidget):
----------
plotter_helper : PlotterHelper
Plotter to add the measure widget to.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter_helper: "Plotter") -> None:
def __init__(self, plotter_helper: "Plotter", dark_mode: bool = False) -> None:
"""Initialize the ``MeasureWidget`` class."""
# Call PlotterWidget ctor
super().__init__(plotter_helper._pl.scene)

self._dark_mode = dark_mode
# Initialize variables
self._actor: vtkActor = None
self.plotter_helper = plotter_helper
Expand Down Expand Up @@ -84,9 +86,13 @@ def callback(self, state: bool) -> None:

def update(self) -> None:
"""Define the measurement widget button parameters."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""
show_measure_vr = self._button.GetRepresentation()
show_measure_icon_file = Path(
Path(__file__).parent / "_images"/ "measurement.png"
Path(__file__).parent / "_images" / f"measurement{is_inv}.png"
)
show_measure_r = vtkPNGReader()
show_measure_r.SetFileName(show_measure_icon_file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ class MeshSliderWidget(PlotterWidget):
----------
plotter_helper : PlotterHelper
Plotter to add the mesh slider widget to.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter_helper: "Plotter") -> None:
def __init__(self, plotter_helper: "Plotter", dark_mode: bool = False) -> None:
"""Initialize the ``MeshSliderWidget`` class."""
# Call PlotterWidget ctor
super().__init__(plotter_helper._pl.scene)

self._dark_mode = dark_mode
# Initialize variables
self._widget_actor: vtkActor = None
self.plotter_helper = plotter_helper
Expand Down Expand Up @@ -101,9 +103,13 @@ def callback(self, state: bool) -> None:

def update(self) -> None:
"""Define the mesh slider widget button parameters."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""
show_measure_vr = self._button.GetRepresentation()
show_measure_icon_file = Path(
Path(__file__).parent / "_images"/ "planecut.png"
Path(__file__).parent / "_images" / f"planecut{is_inv}.png"
)
show_measure_r = vtkPNGReader()
show_measure_r.SetFileName(show_measure_icon_file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ class Ruler(PlotterWidget):
----------
plotter : ~pyvista.Plotter
Provides the plotter to add the ruler widget to.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter: Plotter) -> None:
def __init__(self, plotter: Plotter, dark_mode: bool = False) -> None:
"""Initialize the ``Ruler`` class."""
# Call PlotterWidget ctor
super().__init__(plotter)

self._dark_mode = dark_mode
# Initialize variables
self._actor: vtkActor = None
self._button: vtkButtonWidget = self.plotter.add_checkbox_button_widget(
Expand Down Expand Up @@ -76,16 +78,20 @@ def callback(self, state: bool) -> None:
show_xaxis=True,
show_yaxis=True,
show_zaxis=True,
color="black",
color="white" if self._dark_mode else "black",
xtitle="X Axis [m]",
ytitle="Y Axis [m]",
ztitle="Z Axis [m]",
)

def update(self) -> None:
"""Define the configuration and representation of the ruler widget button."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""
show_ruler_vr = self._button.GetRepresentation()
show_ruler_icon_file = Path(Path(__file__).parent / "_images" / "ruler.png")
show_ruler_icon_file = Path(Path(__file__).parent / "_images" / f"ruler{is_inv}.png")
show_ruler_r = vtkPNGReader()
show_ruler_r.SetFileName(show_ruler_icon_file)
show_ruler_r.Update()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ class ScreenshotButton(PlotterWidget):
----------
plotter : ~pyvista.Plotter
Provides the plotter to add the screenshot widget to.
dark_mode : bool, optional
Whether to activate the dark mode or not.

"""

def __init__(self, plotter: Plotter) -> None:
def __init__(self, plotter: Plotter, dark_mode: bool = False) -> None:
"""Initialize the ``ScreenshotButton`` class."""
# Call PlotterWidget ctor
super().__init__(plotter)

self._dark_mode = dark_mode
# Initialize variables
self._actor: vtkActor = None
self._button: vtkButtonWidget = self.plotter._pl.scene.add_checkbox_button_widget(
Expand All @@ -69,8 +71,12 @@ def callback(self, state: bool) -> None:

def update(self) -> None:
"""Define the configuration and representation of the screenshot widget button."""
if self._dark_mode:
is_inv = "_inv"
else:
is_inv = ""
show_vr = self._button.GetRepresentation()
show_icon_file = Path(Path(__file__).parent / "_images" / "screenshot.png")
show_icon_file = Path(Path(__file__).parent / "_images" / f"screenshot{is_inv}.png")
show_r = vtkPNGReader()
show_r.SetFileName(show_icon_file)
show_r.Update()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
class ViewDirection(Enum):
"""Provides an enum with the available views."""

XYPLUS = 0, "+xy.png", (5, 220)
XYMINUS = 1, "-xy.png", (5, 251)
XZPLUS = 2, "+xz.png", (5, 282)
XZMINUS = 3, "-xz.png", (5, 313)
YZPLUS = 4, "+yz.png", (5, 344)
YZMINUS = 5, "-yz.png", (5, 375)
ISOMETRIC = 6, "isometric.png", (5, 406)
XYPLUS = 0, "+xy", (5, 220)
XYMINUS = 1, "-xy", (5, 251)
XZPLUS = 2, "+xz", (5, 282)
XZMINUS = 3, "-xz", (5, 313)
YZPLUS = 4, "+yz", (5, 344)
YZMINUS = 5, "-yz", (5, 375)
ISOMETRIC = 6, "isometric", (5, 406)


class ViewButton(Button):
Expand All @@ -49,12 +49,13 @@ class ViewButton(Button):
Plotter to draw the buttons on.
direction : ViewDirection
Direction of the view.

dark_mode : bool, optional
Whether to activate the dark mode or not.
"""

def __init__(self, plotter: Plotter, direction: tuple):
def __init__(self, plotter: Plotter, direction: tuple, dark_mode: bool = False) -> None:
"""Initialize the ``ViewButton`` class."""
super().__init__(plotter, direction)
super().__init__(plotter, direction, dark_mode)
self.direction = direction
self.update()

Expand Down
Loading