improve gauge function signatures
This commit is contained in:
@@ -2,9 +2,10 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
from dataclasses import dataclass
|
||||
from types import TracebackType
|
||||
from typing import Any, Generic, TypeVar, cast
|
||||
from typing import Any, Generic, Literal, TypeVar, cast
|
||||
|
||||
import dearpygui.dearpygui as dpg
|
||||
|
||||
@@ -23,7 +24,18 @@ from .gauges import (
|
||||
)
|
||||
from .renderer import GaugeRenderer
|
||||
from .state import GaugeState, register_gauge
|
||||
from .types import Tag
|
||||
from .themes import GaugeStyle, GaugeTheme
|
||||
from .types import (
|
||||
AnimationConfig,
|
||||
Callback,
|
||||
GaugeMarker,
|
||||
GaugeValue,
|
||||
SmoothingConfig,
|
||||
StatusState,
|
||||
Tag,
|
||||
ThresholdBand,
|
||||
ValueFormatter,
|
||||
)
|
||||
|
||||
ConfigT = TypeVar("ConfigT", bound=GaugeConfig)
|
||||
|
||||
@@ -138,92 +150,463 @@ def create_gauge_context(gauge_type: str, config: ConfigT) -> GaugeContext[Confi
|
||||
return GaugeContext(state)
|
||||
|
||||
|
||||
def gauge_panel(**config: Any) -> LayoutContext:
|
||||
def gauge_panel(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
show: bool = True,
|
||||
border: bool = True,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
tooltip: str | None = None,
|
||||
**config: Any,
|
||||
) -> LayoutContext:
|
||||
"""Create a lightweight child-window container for related gauges."""
|
||||
if not _dpg_context_active:
|
||||
return LayoutContext(None)
|
||||
tag = config.pop("tag", 0)
|
||||
label = config.pop("label", None)
|
||||
tooltip = config.pop("tooltip", None)
|
||||
container = dpg.add_child_window(
|
||||
tag=tag,
|
||||
label=label,
|
||||
width=config.pop("width", 0),
|
||||
height=config.pop("height", 0),
|
||||
show=config.pop("show", True),
|
||||
border=config.pop("border", True),
|
||||
autosize_x=config.pop("autosize_x", False),
|
||||
autosize_y=config.pop("autosize_y", False),
|
||||
tag=tag or 0,
|
||||
label=label or "",
|
||||
width=width,
|
||||
height=height,
|
||||
show=show,
|
||||
border=border,
|
||||
autosize_x=autosize_x,
|
||||
autosize_y=autosize_y,
|
||||
**config,
|
||||
)
|
||||
_add_tooltip(container, tooltip)
|
||||
return LayoutContext(container)
|
||||
|
||||
|
||||
def gauge_grid(**config: Any) -> LayoutContext:
|
||||
def gauge_grid(
|
||||
*,
|
||||
columns: int = 1,
|
||||
tag: Tag | None = None,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
show: bool = True,
|
||||
**config: Any,
|
||||
) -> LayoutContext:
|
||||
"""Create a lightweight horizontal gauge layout container."""
|
||||
if not _dpg_context_active:
|
||||
return LayoutContext(None)
|
||||
columns = max(int(config.pop("columns", 1)), 1)
|
||||
columns = max(int(columns), 1)
|
||||
container = dpg.add_group(
|
||||
tag=config.pop("tag", 0),
|
||||
width=config.pop("width", 0),
|
||||
height=config.pop("height", 0),
|
||||
show=config.pop("show", True),
|
||||
tag=tag or 0,
|
||||
width=width,
|
||||
height=height,
|
||||
show=show,
|
||||
horizontal=columns > 1,
|
||||
**config,
|
||||
)
|
||||
return LayoutContext(container)
|
||||
|
||||
|
||||
def analog_gauge(**config: Any) -> GaugeContext[AnalogGaugeConfig]:
|
||||
def analog_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
start_angle: float = 225.0,
|
||||
end_angle: float = -45.0,
|
||||
major_ticks: int = 8,
|
||||
minor_ticks: int = 4,
|
||||
show_tick_labels: bool = True,
|
||||
needle_length: float = 0.82,
|
||||
needle_width: float = 3.0,
|
||||
center_cap_radius: float = 7.0,
|
||||
arc_width: float = 8.0,
|
||||
maintain_aspect: bool = True,
|
||||
redline_start: float | None = None,
|
||||
**config: Any,
|
||||
) -> GaugeContext[AnalogGaugeConfig]:
|
||||
"""Create an analog dial gauge with ticks, needle, thresholds, and markers."""
|
||||
return create_gauge_context("analog", AnalogGaugeConfig(**config))
|
||||
return create_gauge_context("analog", AnalogGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def digital_gauge(**config: Any) -> GaugeContext[DigitalGaugeConfig]:
|
||||
def digital_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
**config: Any,
|
||||
) -> GaugeContext[DigitalGaugeConfig]:
|
||||
"""Create a large numeric readout gauge."""
|
||||
return create_gauge_context("digital", DigitalGaugeConfig(**config))
|
||||
return create_gauge_context("digital", DigitalGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def bar_gauge(**config: Any) -> GaugeContext[BarGaugeConfig]:
|
||||
def bar_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
orientation: Literal["horizontal", "vertical"] = "horizontal",
|
||||
fill_mode: Literal["clamp", "centered"] = "clamp",
|
||||
corner_radius: float = 4.0,
|
||||
show_scale: bool = True,
|
||||
stretch: bool = True,
|
||||
**config: Any,
|
||||
) -> GaugeContext[BarGaugeConfig]:
|
||||
"""Create a horizontal or vertical fill bar gauge."""
|
||||
return create_gauge_context("bar", BarGaugeConfig(**config))
|
||||
return create_gauge_context("bar", BarGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def level_gauge(**config: Any) -> GaugeContext[LevelGaugeConfig]:
|
||||
def level_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
orientation: Literal["horizontal", "vertical"] = "vertical",
|
||||
fill_mode: Literal["clamp", "centered"] = "clamp",
|
||||
corner_radius: float = 4.0,
|
||||
show_scale: bool = True,
|
||||
stretch: bool = True,
|
||||
**config: Any,
|
||||
) -> GaugeContext[LevelGaugeConfig]:
|
||||
"""Create a tank or level-style vertical gauge."""
|
||||
return create_gauge_context("level", LevelGaugeConfig(**config))
|
||||
return create_gauge_context("level", LevelGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def status_light(**config: Any) -> GaugeContext[StatusLightConfig]:
|
||||
def status_light(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
state: str | bool | int = False,
|
||||
states: Mapping[Any, StatusState] | None = None,
|
||||
blink: bool = False,
|
||||
pulse: bool = False,
|
||||
**config: Any,
|
||||
) -> GaugeContext[StatusLightConfig]:
|
||||
"""Create an LED-style status indicator gauge."""
|
||||
return create_gauge_context("status_light", StatusLightConfig(**config))
|
||||
return create_gauge_context("status_light", StatusLightConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def segmented_gauge(**config: Any) -> GaugeContext[SegmentedGaugeConfig]:
|
||||
def segmented_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
orientation: Literal["horizontal", "vertical"] = "horizontal",
|
||||
fill_mode: Literal["clamp", "centered"] = "clamp",
|
||||
corner_radius: float = 4.0,
|
||||
show_scale: bool = True,
|
||||
stretch: bool = True,
|
||||
segments: int = 10,
|
||||
**config: Any,
|
||||
) -> GaugeContext[SegmentedGaugeConfig]:
|
||||
"""Create a segmented strip gauge for shift-light or cell-style displays."""
|
||||
return create_gauge_context("segmented", SegmentedGaugeConfig(**config))
|
||||
return create_gauge_context("segmented", SegmentedGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def compass_gauge(**config: Any) -> GaugeContext[CompassGaugeConfig]:
|
||||
def compass_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 360.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
start_angle: float = 90.0,
|
||||
end_angle: float = -270.0,
|
||||
major_ticks: int = 8,
|
||||
minor_ticks: int = 4,
|
||||
show_tick_labels: bool = True,
|
||||
needle_length: float = 0.82,
|
||||
needle_width: float = 3.0,
|
||||
center_cap_radius: float = 7.0,
|
||||
arc_width: float = 8.0,
|
||||
maintain_aspect: bool = True,
|
||||
redline_start: float | None = None,
|
||||
**config: Any,
|
||||
) -> GaugeContext[CompassGaugeConfig]:
|
||||
"""Create a compass gauge that wraps numeric headings to 0-360 degrees."""
|
||||
return create_gauge_context("compass", CompassGaugeConfig(**config))
|
||||
return create_gauge_context("compass", CompassGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def thermometer_gauge(**config: Any) -> GaugeContext[ThermometerGaugeConfig]:
|
||||
def thermometer_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
orientation: Literal["horizontal", "vertical"] = "vertical",
|
||||
fill_mode: Literal["clamp", "centered"] = "clamp",
|
||||
corner_radius: float = 4.0,
|
||||
show_scale: bool = True,
|
||||
stretch: bool = True,
|
||||
**config: Any,
|
||||
) -> GaugeContext[ThermometerGaugeConfig]:
|
||||
"""Create a thermometer-style temperature gauge."""
|
||||
return create_gauge_context("thermometer", ThermometerGaugeConfig(**config))
|
||||
return create_gauge_context(
|
||||
"thermometer", ThermometerGaugeConfig(**_config_from_locals(locals()))
|
||||
)
|
||||
|
||||
|
||||
def battery_gauge(**config: Any) -> GaugeContext[BatteryGaugeConfig]:
|
||||
def battery_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
orientation: Literal["horizontal", "vertical"] = "vertical",
|
||||
fill_mode: Literal["clamp", "centered"] = "clamp",
|
||||
corner_radius: float = 4.0,
|
||||
show_scale: bool = True,
|
||||
stretch: bool = True,
|
||||
charging: bool | None = None,
|
||||
**config: Any,
|
||||
) -> GaugeContext[BatteryGaugeConfig]:
|
||||
"""Create a battery-style percentage or value gauge."""
|
||||
return create_gauge_context("battery", BatteryGaugeConfig(**config))
|
||||
return create_gauge_context("battery", BatteryGaugeConfig(**_config_from_locals(locals())))
|
||||
|
||||
|
||||
def multi_value_gauge(**config: Any) -> GaugeContext[MultiValueGaugeConfig]:
|
||||
def multi_value_gauge(
|
||||
*,
|
||||
tag: Tag | None = None,
|
||||
label: str | None = None,
|
||||
value: GaugeValue = None,
|
||||
min_value: float = 0.0,
|
||||
max_value: float = 100.0,
|
||||
unit: str = "",
|
||||
precision: int = 0,
|
||||
width: int = 0,
|
||||
height: int = 0,
|
||||
autosize_x: bool = False,
|
||||
autosize_y: bool = False,
|
||||
show: bool = True,
|
||||
show_label: bool = True,
|
||||
show_value: bool = True,
|
||||
show_unit: bool = True,
|
||||
tooltip: str | None = None,
|
||||
callback: Callback | None = None,
|
||||
user_data: Any = None,
|
||||
theme: str | GaugeTheme | None = None,
|
||||
style: GaugeStyle | None = None,
|
||||
animation: AnimationConfig | bool | None = None,
|
||||
smoothing: SmoothingConfig | bool | None = None,
|
||||
clamp: bool = True,
|
||||
format_value: ValueFormatter | None = None,
|
||||
thresholds: Sequence[ThresholdBand] = (),
|
||||
markers: Sequence[GaugeMarker] = (),
|
||||
values: Mapping[str, GaugeValue] | None = None,
|
||||
**config: Any,
|
||||
) -> GaugeContext[MultiValueGaugeConfig]:
|
||||
"""Create a compact grouped key/value readout gauge."""
|
||||
return create_gauge_context("multi_value", MultiValueGaugeConfig(**config))
|
||||
return create_gauge_context(
|
||||
"multi_value", MultiValueGaugeConfig(**_config_from_locals(locals()))
|
||||
)
|
||||
|
||||
|
||||
def _config_from_locals(values: dict[str, Any]) -> dict[str, Any]:
|
||||
config = dict(values.pop("config"))
|
||||
config.update(values)
|
||||
return config
|
||||
|
||||
|
||||
def _default_width(gauge_type: str) -> int:
|
||||
|
||||
Reference in New Issue
Block a user