pytermgui.widgets.pixel_matrix
The module containing all the widgets that can be used to display pixel-based data.
1""" 2The module containing all the widgets that can be used to display 3pixel-based data. 4""" 5 6from __future__ import annotations 7 8from ..ansi_interface import MouseAction, MouseEvent 9from ..parser import markup 10from ..regex import real_length 11from .base import Widget 12 13__all__ = [ 14 "PixelMatrix", 15 "DensePixelMatrix", 16] 17 18 19class PixelMatrix(Widget): 20 """A matrix of pixels. 21 22 The way this object should be used is by accessing & modifying 23 the underlying matrix. This can be done using the set & getitem 24 syntacies: 25 26 ```python3 27 from pytermgui import PixelMatrix 28 29 matrix = PixelMatrix(10, 10, default="white") 30 for y in matrix.rows: 31 for x in matrix.columns: 32 matrix[y, x] = "black" 33 ``` 34 35 The above snippet draws a black diagonal going from the top left 36 to bottom right. 37 38 Each item of the rows should be a single PyTermGUI-parsable color 39 string. For more information about this, see 40 `pytermgui.ansi_interface.Color`. 41 """ 42 43 selected_pixel: tuple[tuple[int, int], str] | None 44 """A tuple of the position & value (color) of the currently hovered pixel.""" 45 46 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 47 """Initializes a PixelMatrix. 48 49 Args: 50 width: The amount of columns the matrix will have. 51 height: The amount of rows the matrix will have. 52 default: The default color to use to initialize the matrix with. 53 """ 54 55 super().__init__(**attrs) 56 57 self.rows = height 58 self.columns = width 59 60 self._matrix = [] 61 62 for _ in range(self.rows): 63 self._matrix.append([default] * self.columns) 64 65 self.selected_pixel = None 66 self.build() 67 68 @classmethod 69 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 70 """Creates a PixelMatrix from the given matrix. 71 72 The given matrix should be a list of rows, each containing a number 73 of cells. It is optimal for all rows to share the same amount of cells. 74 75 Args: 76 matrix: The matrix to use. This is a list of lists of strings 77 with each element representing a PyTermGUI-parseable color. 78 79 Returns: 80 A new type(self). 81 """ 82 83 obj = cls(max(len(row) for row in matrix), len(matrix)) 84 setattr(obj, "_matrix", matrix) 85 obj.build() 86 87 return obj 88 89 def _update_dimensions(self, lines: list[str]): 90 """Updates the dimensions of this matrix. 91 92 Args: 93 lines: A list of lines that the calculations will be based upon. 94 """ 95 96 self.static_width = max(real_length(line) for line in lines) 97 self.height = len(lines) 98 99 def handle_mouse(self, event: MouseEvent) -> bool: 100 """Handles a mouse event. 101 102 On hover, the `selected_pixel` attribute is set to the current pixel. 103 """ 104 105 if event.action is MouseAction.HOVER: 106 xoffset = event.position[0] - self.pos[0] 107 yoffset = event.position[1] - self.pos[1] 108 109 color = self._matrix[yoffset][xoffset // 2] 110 111 self.selected_pixel = ((xoffset // 2, yoffset), color) 112 return True 113 114 return False 115 116 def get_lines(self) -> list[str]: 117 """Returns lines built by the `build` method.""" 118 119 return self._lines 120 121 def build(self) -> list[str]: 122 """Builds the image pixels. 123 124 Returns: 125 The lines that this object will return, until a subsequent `build` call. 126 These lines are stored in the `self._lines` variable. 127 """ 128 129 lines: list[str] = [] 130 for row in self._matrix: 131 line = "" 132 for pixel in row: 133 if len(pixel) > 0: 134 line += f"[@{pixel}] " 135 else: 136 line += "[/] " 137 138 lines.append(markup.parse(line)) 139 140 self._lines = lines 141 self._update_dimensions(lines) 142 143 return lines 144 145 def __getitem__(self, indices: tuple[int, int]) -> str: 146 """Gets a matrix item.""" 147 148 posy, posx = indices 149 return self._matrix[posy][posx] 150 151 def __setitem__(self, indices: tuple[int, int], value: str) -> None: 152 """Sets a matrix item.""" 153 154 posy, posx = indices 155 self._matrix[posy][posx] = value 156 157 158class DensePixelMatrix(PixelMatrix): 159 """A more dense (2x) PixelMatrix. 160 161 Due to each pixel only occupying 1/2 characters in height, accurately 162 determining selected_pixel is impossible, thus the functionality does 163 not exist here. 164 """ 165 166 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 167 """Initializes DensePixelMatrix. 168 169 Args: 170 width: The width of the matrix. 171 height: The height of the matrix. 172 default: The default color to use to initialize the matrix with. 173 """ 174 175 super().__init__(width, height, default, **attrs) 176 177 self.width = width // 2 178 179 def handle_mouse(self, event: MouseEvent) -> bool: 180 """As mentioned in the class documentation, mouse handling is disabled here.""" 181 182 return False 183 184 def build(self) -> list[str]: 185 """Builds the image pixels, using half-block characters. 186 187 Returns: 188 The lines that this object will return, until a subsequent `build` call. 189 These lines are stored in the `self._lines` variable. 190 """ 191 192 lines = [] 193 lines_to_zip: list[list[str]] = [] 194 for row in self._matrix: 195 lines_to_zip.append(row) 196 if len(lines_to_zip) != 2: 197 continue 198 199 line = "" 200 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 201 for bottom, top in zip(bottom_row, top_row): 202 if len(top) + len(bottom) == 0: 203 line += " " 204 continue 205 206 if bottom == "": 207 line += markup.parse(f"[{top}]▀") 208 continue 209 210 markup_str = "@" + top + " " if len(top) > 0 else "" 211 212 markup_str += bottom 213 line += markup.parse(f"[{markup_str}]▄") 214 215 lines.append(line) 216 lines_to_zip = [] 217 218 self._lines = lines 219 self._update_dimensions(lines) 220 221 return lines
20class PixelMatrix(Widget): 21 """A matrix of pixels. 22 23 The way this object should be used is by accessing & modifying 24 the underlying matrix. This can be done using the set & getitem 25 syntacies: 26 27 ```python3 28 from pytermgui import PixelMatrix 29 30 matrix = PixelMatrix(10, 10, default="white") 31 for y in matrix.rows: 32 for x in matrix.columns: 33 matrix[y, x] = "black" 34 ``` 35 36 The above snippet draws a black diagonal going from the top left 37 to bottom right. 38 39 Each item of the rows should be a single PyTermGUI-parsable color 40 string. For more information about this, see 41 `pytermgui.ansi_interface.Color`. 42 """ 43 44 selected_pixel: tuple[tuple[int, int], str] | None 45 """A tuple of the position & value (color) of the currently hovered pixel.""" 46 47 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 48 """Initializes a PixelMatrix. 49 50 Args: 51 width: The amount of columns the matrix will have. 52 height: The amount of rows the matrix will have. 53 default: The default color to use to initialize the matrix with. 54 """ 55 56 super().__init__(**attrs) 57 58 self.rows = height 59 self.columns = width 60 61 self._matrix = [] 62 63 for _ in range(self.rows): 64 self._matrix.append([default] * self.columns) 65 66 self.selected_pixel = None 67 self.build() 68 69 @classmethod 70 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 71 """Creates a PixelMatrix from the given matrix. 72 73 The given matrix should be a list of rows, each containing a number 74 of cells. It is optimal for all rows to share the same amount of cells. 75 76 Args: 77 matrix: The matrix to use. This is a list of lists of strings 78 with each element representing a PyTermGUI-parseable color. 79 80 Returns: 81 A new type(self). 82 """ 83 84 obj = cls(max(len(row) for row in matrix), len(matrix)) 85 setattr(obj, "_matrix", matrix) 86 obj.build() 87 88 return obj 89 90 def _update_dimensions(self, lines: list[str]): 91 """Updates the dimensions of this matrix. 92 93 Args: 94 lines: A list of lines that the calculations will be based upon. 95 """ 96 97 self.static_width = max(real_length(line) for line in lines) 98 self.height = len(lines) 99 100 def handle_mouse(self, event: MouseEvent) -> bool: 101 """Handles a mouse event. 102 103 On hover, the `selected_pixel` attribute is set to the current pixel. 104 """ 105 106 if event.action is MouseAction.HOVER: 107 xoffset = event.position[0] - self.pos[0] 108 yoffset = event.position[1] - self.pos[1] 109 110 color = self._matrix[yoffset][xoffset // 2] 111 112 self.selected_pixel = ((xoffset // 2, yoffset), color) 113 return True 114 115 return False 116 117 def get_lines(self) -> list[str]: 118 """Returns lines built by the `build` method.""" 119 120 return self._lines 121 122 def build(self) -> list[str]: 123 """Builds the image pixels. 124 125 Returns: 126 The lines that this object will return, until a subsequent `build` call. 127 These lines are stored in the `self._lines` variable. 128 """ 129 130 lines: list[str] = [] 131 for row in self._matrix: 132 line = "" 133 for pixel in row: 134 if len(pixel) > 0: 135 line += f"[@{pixel}] " 136 else: 137 line += "[/] " 138 139 lines.append(markup.parse(line)) 140 141 self._lines = lines 142 self._update_dimensions(lines) 143 144 return lines 145 146 def __getitem__(self, indices: tuple[int, int]) -> str: 147 """Gets a matrix item.""" 148 149 posy, posx = indices 150 return self._matrix[posy][posx] 151 152 def __setitem__(self, indices: tuple[int, int], value: str) -> None: 153 """Sets a matrix item.""" 154 155 posy, posx = indices 156 self._matrix[posy][posx] = value
A matrix of pixels.
The way this object should be used is by accessing & modifying the underlying matrix. This can be done using the set & getitem syntacies:
from pytermgui import PixelMatrix
matrix = PixelMatrix(10, 10, default="white")
for y in matrix.rows:
for x in matrix.columns:
matrix[y, x] = "black"
The above snippet draws a black diagonal going from the top left to bottom right.
Each item of the rows should be a single PyTermGUI-parsable color
string. For more information about this, see
pytermgui.ansi_interface.Color
.
47 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 48 """Initializes a PixelMatrix. 49 50 Args: 51 width: The amount of columns the matrix will have. 52 height: The amount of rows the matrix will have. 53 default: The default color to use to initialize the matrix with. 54 """ 55 56 super().__init__(**attrs) 57 58 self.rows = height 59 self.columns = width 60 61 self._matrix = [] 62 63 for _ in range(self.rows): 64 self._matrix.append([default] * self.columns) 65 66 self.selected_pixel = None 67 self.build()
Initializes a PixelMatrix.
Args
- width: The amount of columns the matrix will have.
- height: The amount of rows the matrix will have.
- default: The default color to use to initialize the matrix with.
A tuple of the position & value (color) of the currently hovered pixel.
69 @classmethod 70 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 71 """Creates a PixelMatrix from the given matrix. 72 73 The given matrix should be a list of rows, each containing a number 74 of cells. It is optimal for all rows to share the same amount of cells. 75 76 Args: 77 matrix: The matrix to use. This is a list of lists of strings 78 with each element representing a PyTermGUI-parseable color. 79 80 Returns: 81 A new type(self). 82 """ 83 84 obj = cls(max(len(row) for row in matrix), len(matrix)) 85 setattr(obj, "_matrix", matrix) 86 obj.build() 87 88 return obj
Creates a PixelMatrix from the given matrix.
The given matrix should be a list of rows, each containing a number of cells. It is optimal for all rows to share the same amount of cells.
Args
- matrix: The matrix to use. This is a list of lists of strings with each element representing a PyTermGUI-parseable color.
Returns
A new type(self).
100 def handle_mouse(self, event: MouseEvent) -> bool: 101 """Handles a mouse event. 102 103 On hover, the `selected_pixel` attribute is set to the current pixel. 104 """ 105 106 if event.action is MouseAction.HOVER: 107 xoffset = event.position[0] - self.pos[0] 108 yoffset = event.position[1] - self.pos[1] 109 110 color = self._matrix[yoffset][xoffset // 2] 111 112 self.selected_pixel = ((xoffset // 2, yoffset), color) 113 return True 114 115 return False
Handles a mouse event.
On hover, the selected_pixel
attribute is set to the current pixel.
117 def get_lines(self) -> list[str]: 118 """Returns lines built by the `build` method.""" 119 120 return self._lines
Returns lines built by the build
method.
122 def build(self) -> list[str]: 123 """Builds the image pixels. 124 125 Returns: 126 The lines that this object will return, until a subsequent `build` call. 127 These lines are stored in the `self._lines` variable. 128 """ 129 130 lines: list[str] = [] 131 for row in self._matrix: 132 line = "" 133 for pixel in row: 134 if len(pixel) > 0: 135 line += f"[@{pixel}] " 136 else: 137 line += "[/] " 138 139 lines.append(markup.parse(line)) 140 141 self._lines = lines 142 self._update_dimensions(lines) 143 144 return lines
Builds the image pixels.
Returns
The lines that this object will return, until a subsequent
build
call. These lines are stored in theself._lines
variable.
Inherited Members
- pytermgui.widgets.base.Widget
- set_style
- set_char
- styles
- chars
- keys
- serialized
- is_bindable
- size_policy
- parent_align
- from_data
- bindings
- id
- selectables_length
- selectables
- is_selectable
- static_width
- relative_width
- terminal
- get_change
- contains
- handle_key
- serialize
- copy
- bind
- unbind
- execute_binding
- select
- debug
159class DensePixelMatrix(PixelMatrix): 160 """A more dense (2x) PixelMatrix. 161 162 Due to each pixel only occupying 1/2 characters in height, accurately 163 determining selected_pixel is impossible, thus the functionality does 164 not exist here. 165 """ 166 167 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 168 """Initializes DensePixelMatrix. 169 170 Args: 171 width: The width of the matrix. 172 height: The height of the matrix. 173 default: The default color to use to initialize the matrix with. 174 """ 175 176 super().__init__(width, height, default, **attrs) 177 178 self.width = width // 2 179 180 def handle_mouse(self, event: MouseEvent) -> bool: 181 """As mentioned in the class documentation, mouse handling is disabled here.""" 182 183 return False 184 185 def build(self) -> list[str]: 186 """Builds the image pixels, using half-block characters. 187 188 Returns: 189 The lines that this object will return, until a subsequent `build` call. 190 These lines are stored in the `self._lines` variable. 191 """ 192 193 lines = [] 194 lines_to_zip: list[list[str]] = [] 195 for row in self._matrix: 196 lines_to_zip.append(row) 197 if len(lines_to_zip) != 2: 198 continue 199 200 line = "" 201 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 202 for bottom, top in zip(bottom_row, top_row): 203 if len(top) + len(bottom) == 0: 204 line += " " 205 continue 206 207 if bottom == "": 208 line += markup.parse(f"[{top}]▀") 209 continue 210 211 markup_str = "@" + top + " " if len(top) > 0 else "" 212 213 markup_str += bottom 214 line += markup.parse(f"[{markup_str}]▄") 215 216 lines.append(line) 217 lines_to_zip = [] 218 219 self._lines = lines 220 self._update_dimensions(lines) 221 222 return lines
A more dense (2x) PixelMatrix.
Due to each pixel only occupying 1/2 characters in height, accurately determining selected_pixel is impossible, thus the functionality does not exist here.
167 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 168 """Initializes DensePixelMatrix. 169 170 Args: 171 width: The width of the matrix. 172 height: The height of the matrix. 173 default: The default color to use to initialize the matrix with. 174 """ 175 176 super().__init__(width, height, default, **attrs) 177 178 self.width = width // 2
Initializes DensePixelMatrix.
Args
- width: The width of the matrix.
- height: The height of the matrix.
- default: The default color to use to initialize the matrix with.
180 def handle_mouse(self, event: MouseEvent) -> bool: 181 """As mentioned in the class documentation, mouse handling is disabled here.""" 182 183 return False
As mentioned in the class documentation, mouse handling is disabled here.
185 def build(self) -> list[str]: 186 """Builds the image pixels, using half-block characters. 187 188 Returns: 189 The lines that this object will return, until a subsequent `build` call. 190 These lines are stored in the `self._lines` variable. 191 """ 192 193 lines = [] 194 lines_to_zip: list[list[str]] = [] 195 for row in self._matrix: 196 lines_to_zip.append(row) 197 if len(lines_to_zip) != 2: 198 continue 199 200 line = "" 201 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 202 for bottom, top in zip(bottom_row, top_row): 203 if len(top) + len(bottom) == 0: 204 line += " " 205 continue 206 207 if bottom == "": 208 line += markup.parse(f"[{top}]▀") 209 continue 210 211 markup_str = "@" + top + " " if len(top) > 0 else "" 212 213 markup_str += bottom 214 line += markup.parse(f"[{markup_str}]▄") 215 216 lines.append(line) 217 lines_to_zip = [] 218 219 self._lines = lines 220 self._update_dimensions(lines) 221 222 return lines
Builds the image pixels, using half-block characters.
Returns
The lines that this object will return, until a subsequent
build
call. These lines are stored in theself._lines
variable.
Inherited Members
- pytermgui.widgets.base.Widget
- set_style
- set_char
- styles
- chars
- keys
- serialized
- is_bindable
- size_policy
- parent_align
- from_data
- bindings
- id
- selectables_length
- selectables
- is_selectable
- static_width
- relative_width
- terminal
- get_change
- contains
- handle_key
- serialize
- copy
- bind
- unbind
- execute_binding
- select
- debug