[feature] Define page background color, line color, text color
This is the next step after #219.
Any area that accepts a background color should have the option to set a foreground/text color, e.g. for good contrast against a dark background.
Additionally, the possibility of a "dark theme", with light text and lines on a dark background, would be very appealing.
I'm currently testing some draft code that will be able to read YAML input like this:
X1:
pincount: 4
box:
color: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 12
title:
bgcolor: RD
fontsize: 20
Edit: Any attribute not specified under title is inherited from box.
I guess specifying all this for each connector and cable is not wanted by anyone, but it might be useful to have the option. By grouping these attributes under box and title it is easy to use common templates.
If #214 is accepted and merged, I also have a draft code for harness options that will be able to read YAML input like this:
options:
base:
color: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 16
connector:
bgcolor: RD
cable:
bgcolor: BU
bundle:
bgcolor: GN
Edit: Any attribute not specified under bundle is inherited from cable, and likewise cable from node, connector from node, and node from base.
These will be used for the whole harness unless overridden for some connectors/cables as described in the upper part of my comment.
By moving the title dict into box and likewise into all the option dicts with color/font attributes, it becomes easier to specify common title attributes.
I suggest we consider accepting something like this refined syntax:
options:
bordercolor: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 16
connector:
bgcolor: RD
title:
fontsize: 18
cable:
bgcolor: BU
title:
fontsize: 20
bundle:
bgcolor: GN
connectors:
X1:
pincount: 4
bordercolor: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 12
title:
bgcolor: RD
fontsize: 20
To obtain the above syntax (without the base and box structures) I believe we need to use inheritance in the dataclasses - maybe something like this:
@dataclass
class Look:
"""Colors and font that defines how an element should look like."""
bordercolor: Optional[Color] = None
bgcolor: Optional[Color] = None
fontcolor: Optional[Color] = None
fontname: Optional[PlainText] = None
fontsize: Optional[Points] = None
@dataclass
class NodeLook(Look):
"""How a node look like possibly with a different looking title."""
title: Look = field(default_factory=dict)
@dataclass
class Options(Look):
node: NodeLook = field(default_factory=dict)
connector: NodeLook = field(default_factory=dict)
cable: NodeLook = field(default_factory=dict)
bundle: NodeLook = field(default_factory=dict)
...
@dataclass
class Connector(NodeLook):
...
Such inheritance should also be possible to combine with my suggestions in issue https://github.com/formatc1702/WireViz/issues/56#issuecomment-714798552.
I will need some time to think about the best way to structure the data, but I agree that a dataclass could be a good solution.
Also, you will be pleased to see that my refactoring effort is already beginning to implement some subclassing, similar to what you propose in #56.
I will need some time to think about the best way to structure the data, but I agree that a dataclass could be a good solution.
- See PR #255 for an implementation of
Look~~andNodeLook~~. Edit: TheNodeLookimplementation is not yet rebased and pushed. - Do you like the class names?
VisualAppearanceandNodeVisualAppearanceare too long and complex, I think. - The concept with a
NodeLookcontaining the look attributes of a node together with an optional different look of its title hopefully makes it easy to define a library of YAML templates for reusing popularLookandNodeLookvalue combinations. - What alternatives to
dataclassdo you consider? Named tuple?
Also, you will be pleased to see that my refactoring effort is already beginning to implement some subclassing, similar to what you propose in #56.
Yes, I had a quick look into wv_dataclasses.py and observed the beginning of an inheritance structure. I assume you try to avoid duplicating the same attributes and other properties in different classes, and rather inherit from a common superclass where possible. PR #251 is also a good opportunity to harmonize the set of attributes between similar classes where it makes sense - then the inheritance structure also might get simplified.
- Do you like the class names?
VisualAppearanceandNodeVisualAppearanceare too long and complex, I think.
I propose Style/NodeStyle instead of Look; this would be consistent with the nomenclature in other programming/markup languages.
I am aware that style is currently an attribute for connectors (with style="single" the only currently supported value besides None), but I am strongly considering to consolidate this with the category attribute already present in cables.
Without going off-topic too much, I am envisioning a new category="dual" or similar, for components with exactly two pins, one left and one right, to represent resistors, LEDs, switches and other simple in-line components, and some other ideas that could profit from this.
- What alternatives to
dataclassdo you consider? Named tuple?
Dataclasses are pretty handy, especially when wanting to add some "smart" behavior using __post_init__() and other custom functions. Named tuples might be more memory efficient, but that is not really relevant for our application.
@formatc1702 wrote above:
I propose
Style/NodeStyleinstead ofLook; this would be consistent with the nomenclature in other programming/markup languages.I am aware that
styleis currently an attribute for connectors (withstyle="single"the only currently supported value besidesNone), but I am strongly considering to consolidate this with thecategoryattribute already present in cables.
If the style attribute gets available, then I adjust my suggested syntax to accept an input like this:
options:
style:
bordercolor: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 16
wires:
bordercolor: IV
bgcolor: GY
nodes:
title:
color: YE
connectors:
bgcolor: RD
title:
fontsize: 18
cables:
bgcolor: BU
title:
fontsize: 20
bundles:
bgcolor: GN
connectors:
X1:
pincount: 4
style:
bordercolor: WH
bgcolor: BK
fontcolor: IV
fontname: times
fontsize: 12
title:
bgcolor: RD
fontsize: 20
image:
src: imagefile.png
style:
bgcolor: GY
fontcolor: BK
caption: Text in black
This way, it becomes easy to define and use style templates and even theme templates for the options.style attribute. It also becomes easier to implement the style dataclasses independently of any inheritance between the dataclasses containing style attributes:
@dataclass
class ColorStyle:
"""Colors that defines how a simple element should look like."""
bordercolor: Optional[Color] = None
bgcolor: Optional[Color] = None
@dataclass
class Style(ColorStyle):
"""Colors and font that defines how an element should look like."""
fontcolor: Optional[Color] = None
fontname: Optional[PlainText] = None
fontsize: Optional[Points] = None
@dataclass
class NodeStyle(Style):
"""How a node look like possibly with a different looking title."""
title: Style = field(default_factory=dict)
@dataclass
class DiagramStyle(Style):
"""How a diagram look like possibly with different looking node classes."""
wires: ColorStyle = field(default_factory=dict)
nodes: NodeStyle = field(default_factory=dict)
connectors: NodeStyle = field(default_factory=dict)
cables: NodeStyle = field(default_factory=dict)
bundles: NodeStyle = field(default_factory=dict)
@dataclass
class Options:
color_mode: ColorMode = 'SHORT'
mini_bom_mode: bool = True
style: DiagramStyle = field(default_factory=dict)
@dataclass
class Image:
...
style: Optional[Style] = None
...
@dataclass
class Connector:
...
style: Optional[NodeStyle] = None
...
@dataclass
class Cable:
...
style: Optional[NodeStyle] = None
...