diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index 2ed6e6c..c2c7f5b 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -138,9 +138,10 @@ class AdditionalComponent: @dataclass -class Component(): +class Component: pass + @dataclass class Connector(Component): name: Designator diff --git a/src/wireviz/wv_gv_html.py b/src/wireviz/wv_gv_html.py index cb78c67..c252398 100644 --- a/src/wireviz/wv_gv_html.py +++ b/src/wireviz/wv_gv_html.py @@ -4,7 +4,7 @@ import re from itertools import zip_longest from typing import List, Optional, Union -from wireviz.DataClasses import Cable, Color, Connector, Component, Options +from wireviz.DataClasses import Cable, Color, Component, Connector, Options from wireviz.wv_colors import get_color_hex, translate_color from wireviz.wv_helper import pn_info_string, remove_links from wireviz.wv_table_util import * # TODO: explicitly import each needed tag later @@ -14,7 +14,9 @@ HEADER_MPN = "MPN" HEADER_SPN = "SPN" -def gv_node_component(component: Component, harness_options: Options, pad=None) -> Table: +def gv_node_component( + component: Component, harness_options: Options, pad=None +) -> Table: # If no wires connected (except maybe loop wires)? if isinstance(component, Connector): if not (component.ports_left or component.ports_right): @@ -23,14 +25,14 @@ def gv_node_component(component: Component, harness_options: Options, pad=None) # generate all rows to be shown in the node if component.show_name: str_name = f"{remove_links(component.name)}" - row_name = [colored_cell(str_name, component.bgcolor_title)] + line_name = colored_cell(str_name, component.bgcolor_title) else: - row_name = [] + line_name = None - row_pn = par_number_cell_list(component) + line_pn = part_number_str_list(component) if isinstance(component, Connector): - row_info = [ + line_info = [ html_line_breaks(component.type), html_line_breaks(component.subtype), f"{component.pincount}-pin" if component.show_pincount else None, @@ -38,22 +40,23 @@ def gv_node_component(component: Component, harness_options: Options, pad=None) colorbar_cell(component.color), ] elif isinstance(component, Cable): - row_info = [ + line_info = [ html_line_breaks(component.type), f"{component.wirecount}x" if component.show_wirecount else None, f"{component.gauge_str}" if component.gauge else None, "+ S" if component.shield else None, - f"{component.length} {component.length_unit}" if component.length > 0 else None, + f"{component.length} {component.length_unit}" + if component.length > 0 + else None, translate_color(component.color, harness_options.color_mode), colorbar_cell(component.color), ] - row_image, row_image_caption = image_and_caption_cells(component) - - # row_additional_component_table = get_additional_component_table(self, connector) - row_additional_component_table = None - row_notes = [html_line_breaks(component.notes)] + line_image, line_image_caption = image_and_caption_cells(component) + # line_additional_component_table = get_additional_component_table(self, connector) + line_additional_component_table = None + line_notes = [html_line_breaks(component.notes)] if isinstance(component, Connector): # pin table @@ -77,24 +80,26 @@ def gv_node_component(component: Component, harness_options: Options, pad=None) "cellpadding": 3, "cellborder": 1, } - row_ports = str(Table(pin_rows, attribs=table_attribs)) + line_ports = Table(pin_rows, attribs=table_attribs) else: - row_ports = None + line_ports = None elif isinstance(component, Cable): - row_ports = str(gv_conductor_table(component, harness_options, pad)) + line_ports = gv_conductor_table(component, harness_options, pad) - rows = [ - row_name, - row_pn, - row_info, - row_ports, - row_image, - row_image_caption, - row_additional_component_table, - row_notes, + lines = [ + line_name, + line_pn, + line_info, + line_ports, + line_image, + line_image_caption, + line_additional_component_table, + line_notes, ] - tbl = nested_table(rows) + cell_lists = [make_list_of_cells(line) for line in lines] + + tbl = nested_table(cell_lists) if component.bgcolor: tbl.attribs["bgcolor"] = translate_color(component.bgcolor, "HEX") @@ -108,10 +113,64 @@ def gv_node_component(component: Component, harness_options: Options, pad=None) harness_options.bgcolor_cable, "HEX" ) + return tbl + + +def nested_table(cell_lists: List[Td]) -> Table: + outer_table_attribs = { + "border": 0, + "cellspacing": 0, + "cellpadding": 0, + } + inner_table_attribs = { + "border": 0, + "cellspacing": 0, + "cellpadding": 3, + "cellborder": 1, + } + + rows = [] + for lst in cell_lists: + if len(lst) == 0: + continue # no cells in list + cells = [item for item in lst if item.contents is not None] + if len(cells) == 0: + continue # no cells in list that are not None + if ( + len(cells) == 1 + and isinstance(cells[0].contents, Table) + and not "!" in cells[0].contents.attribs.get("id", "") + ): + # cell content is already a table, no need to re-wrap it; + # unless explicitly asked to by a "!" in the ID field + # as used by image_and_caption_cells() + inner_table = cells[0].contents + else: + # nest cell content inside a table + inner_table = Table(Tr(cells), attribs=inner_table_attribs) + rows.append(Tr(Td(inner_table))) + if len(rows) == 0: # create dummy row to avoid GraphViz errors due to empty