WireViz icon indicating copy to clipboard operation
WireViz copied to clipboard

[feature] Define page background color, line color, text color

Open 17o2 opened this issue 4 years ago • 7 comments

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.

image image

17o2 avatar Mar 20 '21 14:03 17o2

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.

kvid avatar May 05 '21 19:05 kvid

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.

kvid avatar May 05 '21 21:05 kvid

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.

kvid avatar Oct 23 '21 02:10 kvid

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.

17o2 avatar Oct 23 '21 09:10 17o2

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 ~~and NodeLook~~. Edit: The NodeLook implementation is not yet rebased and pushed.
  • Do you like the class names? VisualAppearance and NodeVisualAppearance are too long and complex, I think.
  • The concept with a NodeLook containing 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 popular Look and NodeLook value combinations.
  • What alternatives to dataclass do 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.

kvid avatar Oct 23 '21 21:10 kvid

  • Do you like the class names? VisualAppearance and NodeVisualAppearance are 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 dataclass do 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.

17o2 avatar Oct 25 '21 17:10 17o2

@formatc1702 wrote above:

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.

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
    ...

kvid avatar Jan 30 '22 03:01 kvid