Source code for matrix_viewer._tab_struct


import numpy as np
import tkinter as tk

from ._tab_table import ViewerTabTable
from ._tab_numpy import matches_tab_numpy

[docs]class ViewerTabStruct(ViewerTabTable): """A viewer tab that can be used to visualize a class, list, dict and some other container types.""" def __init__(self, viewer, object, title=None, font_size=None): """Creates a new tab in the specified viewer. Please use viewer.view instead because this selects the appropriate Tab subclass.""" self.object = object self._calc_font(font_size) default_title = object.__class__.__name__ # query all attributes associated with the object if type(self.object) in (set, tuple): self.object_attributes = list(("", value) for value in self.object) self.row_heading_heading = "" default_title = f"{self.object.__class__.__name__} with {len(self.object)} elements" elif type(self.object) == list: self.object_attributes = list((str(i), value) for i, value in enumerate(self.object)) self.row_heading_heading = "" default_title = f"list with {len(self.object)} elements" elif isinstance(self.object, dict): self.object_attributes = list(self.object.items()) self.row_heading_heading = "Key" default_title = f"{type(self.object).__name__} with {len(self.object)} elements" else: self.object_attributes = [] for element_name in dir(self.object): try: attr = getattr(self.object, element_name) if (not callable(attr)) and (element_name not in ["__dict__", "__doc__", "__module__", "__weakref__"]): self.object_attributes.append((element_name, attr)) except BaseException as e: # print(f'matrix_viewer: exception querying {element_name}: {e}') pass self.row_heading_heading = "Name" # format the values self.object_value_strings = [] self.object_value_clickable = [] for _, value in self.object_attributes: if isinstance(value, (int, float)): # also matches bool because bool is a subclass of int value_string = str(value) elif type(value) in [str, bytes]: value_string = str(value) if '\n' in value_string: value_string = f"multiline string with {len(value)} characters" elif value is None: value_string = "None" elif type(value) == np.ndarray: value_string = f"{value.shape} {value.dtype} ndarray" elif type(value) in [list, dict, set, tuple]: value_string = f"{value.__class__.__name__} with {len(value)} elements" else: value_string = str(type(value)) clickable = matches_tab_numpy(value) or matches_tab_struct(value) or (type(value).__name__ in ["ndarray", "Tensor"]) self.object_value_strings.append(value_string) self.object_value_clickable.append(clickable) self._font_changed() if title is None: title = default_title ViewerTabTable.__init__(self, viewer, title, 1, len(self.object_attributes)) self.clickable_color = "#000077" self.clickable_hover_color = "#0000ff" self.canvas1.bind("<ButtonRelease-1>", self._on_mouse_release) def _font_changed(self): self.max_text_width = max(self.cell_font.measure(s) for s in (self.object_value_strings + ['Value'])) row_headings = list(attr[0] for attr in self.object_attributes) self.row_heading_text_width = max(self.cell_font.measure(s) for s in (row_headings + [self.row_heading_heading])) def _on_mouse_release(self, event): hit_x, hit_y = self._calc_hit_cell(event.x, event.y) if (hit_x is not None) and (hit_x != -1) and (hit_y != -1): assert hit_x == 0 if self.object_value_clickable[hit_y]: self.viewer.view(self.object_attributes[hit_y][1]) new_tab_index = self.viewer.paned.index('end') - 1 # assumes that the new tab is the last tab self.viewer.paned.select(new_tab_index) # go to the currently added tab def _draw_cells(self): x = self.cell_hpadding y = self.cell_vpadding self.canvas1.create_text(x, y, text=self.row_heading_heading, font=self.cell_font, anchor='nw') y += self.cell_height for i_row in range(self.yscroll_item, min(self.yscroll_item + self.yscroll_page_size + 1, self.yscroll_items)): self.canvas1.create_text(x, y, text=self.object_attributes[i_row][0], font=self.cell_font, anchor='nw') y += self.cell_height x += self.row_heading_width for i_column in range(self.xscroll_item, min(self.xscroll_item + self.xscroll_page_size + 1, self.xscroll_items)): y = self.cell_vpadding self.canvas1.create_text(x, y, text="Value", font=self.cell_font, anchor='nw') y += self.cell_height for i_row in range(self.yscroll_item, min(self.yscroll_item + self.yscroll_page_size + 1, self.yscroll_items)): if self.object_value_clickable[i_row]: self.canvas1.create_text( x, y, text=self.object_value_strings[i_row], font=self.cell_font, anchor='nw', fill=self.clickable_color, activefill=self.clickable_hover_color, ) else: self.canvas1.create_text(x, y, text=self.object_value_strings[i_row], font=self.cell_font, anchor='nw') y += self.cell_height x += self.cell_width
def matches_tab_struct(object): return (not isinstance(object, (int, float, str, bytes, np.ndarray))) and (type(object).__name__ != "Tensor") and (object is not None)