peng3d.gui.style - Generic Styles for Widgets

class peng3d.gui.style.Borderstyle[source]

Base class for all border styles.

Each border style class serves a single style, although some parameters may be adjustable.

Currently, border style classes are not instantiated per widget, but rather rely on class methods. This reduces memory overhead but may be changed in the future.

For backwards compatibility, border style classes themselves compare equal with their old-style string equivalents. This is accomplished with a metaclass and not necessary to emulate for new styles and may be removed in a future version.

classmethod get_colormap(widget: widgets.BasicWidget, bg: List[int], o: List[int], i: List[int], s: List[int], h: List[int], state: Optional[str] = None)[source]

Gets the color map for a button-style widget.

TODO: document return format

Parameters:
  • widget (BasicWidget) – Widget that the color map belongs to
  • bg (ColorRGB) – Background color this widget is placed on
  • o (ColorRGB) – Outer color, usually same as the background
  • i (ColorRGB) – Inner color, usually lighter than the background
  • s (ColorRGB) – Shadow color, usually quite a bit darker than the background
  • h (ColorRGB) – Highlight color, usually quite a bit lighter than the background
  • state (str) – Optional widget state override
Returns:

Return type:

class peng3d.gui.style.FlatBorder[source]
classmethod get_colormap(widget: widgets.BasicWidget, bg: List[int], o: List[int], i: List[int], s: List[int], h: List[int], state: Optional[str] = None)[source]

Gets the color map for a button-style widget.

TODO: document return format

Parameters:
  • widget (BasicWidget) – Widget that the color map belongs to
  • bg (ColorRGB) – Background color this widget is placed on
  • o (ColorRGB) – Outer color, usually same as the background
  • i (ColorRGB) – Inner color, usually lighter than the background
  • s (ColorRGB) – Shadow color, usually quite a bit darker than the background
  • h (ColorRGB) – Highlight color, usually quite a bit lighter than the background
  • state (str) – Optional widget state override
Returns:

Return type:

class peng3d.gui.style.GradientBorder[source]
classmethod get_colormap(widget: widgets.BasicWidget, bg: List[int], o: List[int], i: List[int], s: List[int], h: List[int], state: Optional[str] = None)[source]

Gets the color map for a button-style widget.

TODO: document return format

Parameters:
  • widget (BasicWidget) – Widget that the color map belongs to
  • bg (ColorRGB) – Background color this widget is placed on
  • o (ColorRGB) – Outer color, usually same as the background
  • i (ColorRGB) – Inner color, usually lighter than the background
  • s (ColorRGB) – Shadow color, usually quite a bit darker than the background
  • h (ColorRGB) – Highlight color, usually quite a bit lighter than the background
  • state (str) – Optional widget state override
Returns:

Return type:

class peng3d.gui.style.OldshadowBorder[source]
classmethod get_colormap(widget: widgets.BasicWidget, bg: List[int], o: List[int], i: List[int], s: List[int], h: List[int], state: Optional[str] = None)[source]

Gets the color map for a button-style widget.

TODO: document return format

Parameters:
  • widget (BasicWidget) – Widget that the color map belongs to
  • bg (ColorRGB) – Background color this widget is placed on
  • o (ColorRGB) – Outer color, usually same as the background
  • i (ColorRGB) – Inner color, usually lighter than the background
  • s (ColorRGB) – Shadow color, usually quite a bit darker than the background
  • h (ColorRGB) – Highlight color, usually quite a bit lighter than the background
  • state (str) – Optional widget state override
Returns:

Return type:

class peng3d.gui.style.MaterialBorder[source]
classmethod get_colormap(widget: widgets.BasicWidget, bg: List[int], o: List[int], i: List[int], s: List[int], h: List[int], state: Optional[str] = None)[source]

Gets the color map for a button-style widget.

TODO: document return format

Parameters:
  • widget (BasicWidget) – Widget that the color map belongs to
  • bg (ColorRGB) – Background color this widget is placed on
  • o (ColorRGB) – Outer color, usually same as the background
  • i (ColorRGB) – Inner color, usually lighter than the background
  • s (ColorRGB) – Shadow color, usually quite a bit darker than the background
  • h (ColorRGB) – Highlight color, usually quite a bit lighter than the background
  • state (str) – Optional widget state override
Returns:

Return type:

peng3d.gui.style.BORDERSTYLES = {'flat': <class 'peng3d.gui.style.FlatBorder'>, 'gradient': <class 'peng3d.gui.style.GradientBorder'>, 'material': <class 'peng3d.gui.style.MaterialBorder'>, 'oldshadow': <class 'peng3d.gui.style.OldshadowBorder'>}

Map of border style names to classes that implement them.

See the documentation of each class for descriptions.

peng3d.gui.style.norm_borderstyle(borderstyle: Union[str, Type[peng3d.gui.style.Borderstyle]]) → Type[peng3d.gui.style.Borderstyle][source]

Normalizes border styles to Borderstyle subclasses.

Parameters:borderstyle (Either str or Borderstyle subclass) – Value to normalize
Returns:Normalized value
Return type:Borderstyle subclass
Raises:TypeError – if an unexpected value was given
class peng3d.gui.style.Style(parent: Union[Style, Dict[str, Union[float, str, Type[Borderstyle]]], None] = None, overrides: Optional[Dict[str, Union[float, str, Type[Borderstyle]]]] = None)[source]

Core of the hierarchical style system.

This class allows for easily inheriting styles from a parent (e.g. submenu or menu) while allowing dynamic overwriting at any level in the hierarchy. For example, a specific submenu could have a different font that would then be automatically applied to all widgets within it, unless the font was overridden for the widget locally.

When reading a style attribute, this class first checks if it has a local override for that attribute. If so, it will be returned. If the attribute wasn’t overridden locally, the parent is queried and its result returned. The root of this hierarchy is the style attribute of the Peng() singleton, which uses the styles defined in DEFAULT_STYLE as a default. If a style attribute is not found anywhere, a KeyError will be raised.

When writing a style attribute, a local override is created. This causes all subsequent accesses to the style attribute within this instance and all children (e.g. widgets within a submenu) to read back the new value. Deleting the style attribute will reset this override and thus reset the read value back to the parent value.

Note that changes in an attribute usually require a redraw of the affected widgets. If a redraw is not performed, weird graphical glitches may happen.

This class is very flexible and allows several different modes of access.

First, it is possible to use it like a dict, e.g. style["font"]. It is possible to read, write and delete using this method. All styles are accessible in this manner and arbitrary strings are allowed as keys, though it is recommended to stick to valid Python identifiers.

For convenience, it is also possible to access style attributes as literal attributes of a Style instance, e.g. style.font. Note that this only allows accesses to style attributes whose name is a valid python identifier and that are not in the list of reserved attributes, stored in the class attribute Style.ATTRIBUTES. It is also not possible to access style attributes that start with an underscore or are methods of Style this way. This access mode also supports read, write and delete accesses.

Note that unlike the helpers default_property and default, Style does not reset an override if a write with a value of None is performed.

ATTRIBUTES = ['parent', 'ATTRIBUTES']

Internal list of attributes that are reserved and cannot be used for styles via attribute access.

This list may be extended in the future. Note that all attributes that start with an underscore are also implicitly reserved.

add_watcher(watch_sel, callback=None)[source]

Adds a watcher for specific changes in local styles.

Watchers can be used to automatically update widgets or other visual elements whenever the effective value of a style attribute changes. This includes scenarios where the (not locally overridden) style attribute of the parent changes, causing a change in the effective local value.

The watcher system tries its best to remove unnecessary triggers and double-triggers, but they may still occur under some circumstances. Thus, it is recommended to only use (semi-)idempotent functions as callbacks. A popular example for a suitable callback would be the redraw() method of widgets, since it will only queue the actual redraw and thus prevents extraneous redraws.

This method accepts either an instance of StyleWatcher or a selector string followed by a callback function.

Selectors are strings that describe what changes to listen to. Currently, selectors are quite rudimentary, but it is planned to add a more sophisticated system later.

The special * selector matches all changes and will thus be triggered on any change of any local attribute.

Alternatively, all other strings will trigger on the change of a style attribute with their exact name.

Callback functions can either take no arguments or the old value of the style attribute as a single argument.

get(key: str, default: Union[float, str, Type[Borderstyle], None] = None) → Union[float, str, Type[peng3d.gui.style.Borderstyle], None][source]

Returns the effective value of the given key or the given default if it couldn’t be found.

is_overridden(key: str) → bool[source]

Checks whether a given key is currently being overridden.

If this returns true, any change in parent styles will not affect the value of the given style attribute.

Parameters:key (str) – Key to check
Returns:whether key is currently overridden
Return type:bool
override_if_not_none(key: str, value: Union[float, str, Type[Borderstyle], None]) → None[source]

Overrides the given key if the provided value is not None.

This helper allows for easy style overriding via keyword arguments. Simply create a keyword argument in the constructor of an object that uses styles and set the default of that keyword argument to None. In the constructor, you can then call this function like so:

self.style.override_if_not_none("font", font)

Note that this method is unsuitable for style attributes that may actually want to have a value of None.

Parameters:
  • key (str) – Key to override
  • value (Optional[StyleValue]) – value used to override if it is not None
Returns:

None

Return type:

None

parent = None

Attribute that stores the parent of this style.

May be changed during runtime, though most widgets will require a redraw to fully respect changed effective style values.

It is usually not required to write to this attribute, since widgets do not currently support being moved between different submenus or even menus.

update(_overrides: Optional[Dict[str, Union[float, str, Type[Borderstyle]]]] = None, **kwargs) → None[source]

Updates several style attributes at the same time.

Note that this method only supports creating and modifying overrides. Keys not present in the given data will be kept as is.

This method supports both passing in a dictionary and passing in keyword attributes. Note that in the case of a style attribute being present in both the dictionary and a keyword argument, the keyword argument takes precedence.

Parameters:
  • _overrides (Optional[Dict[str, StyleValue]]) – Optional dictionary to add/modify overrides from
  • kwargs (StyleValue) – Optional keyword arguments to add/modify overrides from
Returns:

None

Return type:

None

peng3d.gui.style.DEFAULT_STYLE = {'border': (4, 4), 'borderstyle': <class 'peng3d.gui.style.FlatBorder'>, 'font': 'Arial', 'font_color': (62, 67, 73, 255), 'font_size': 16}

Default styles for all parts of peng3d.

These styles represent a sensible default for common use cases.

For application-wide changes, it is recommended to override the styles in question using the peng3d.peng.Peng.style attribute.