"""Widgets for inputting values."""
from __future__ import annotations
from enum import Enum
from typing import TYPE_CHECKING, TypeVar, Generic, Tuple
from dearpygui import dearpygui as dpgcore
from dearpygui_obj import _register_item_type
from dearpygui_obj.wrapper.widget import Widget, ItemWidgetMx, ValueWidgetMx, ConfigProperty
if TYPE_CHECKING:
from typing import Optional
## Input Boxes
[docs]@_register_item_type('mvAppItemType::InputText')
class InputText(Widget, ItemWidgetMx, ValueWidgetMx[str]):
"""A text input box."""
value: str #: The inputted text.
hint: str = ConfigProperty()
multiline: bool = ConfigProperty()
no_spaces: bool = ConfigProperty()
uppercase: bool = ConfigProperty()
tab_input: bool = ConfigProperty()
decimal: bool = ConfigProperty()
hexadecimal: bool = ConfigProperty()
readonly: bool = ConfigProperty()
password: bool = ConfigProperty()
scientific: bool = ConfigProperty()
label: str = ConfigProperty()
on_enter: bool = ConfigProperty()
def __init__(self, label: str = None, value: str = '', **config):
super().__init__(label=label, default_value=value, **config)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_input_text(self.id, **dpg_args)
## Kind of went overboard with the type checking here...
## probably would have been good enough just to drop annotations for number inputs
## Two type parameters are required because of how DPG multi-inputs work
_TElem = TypeVar('_TElem')
_TInput = TypeVar('_TInput')
# noinspection PyAbstractClass
## Sliders
# noinspection PyAbstractClass
[docs]@_register_item_type('mvAppItemType::SliderFloat')
class SliderFloat(SliderInput[float, float]):
"""A slider for a float value.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = 0.0
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_float(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderFloat2')
class SliderFloat2(SliderInput[float, Tuple[float, float]]):
"""A slider for 2 float values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_float2(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderFloat3')
class SliderFloat3(SliderInput[float, Tuple[float, float, float]]):
"""A slider for 3 float values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_float3(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderFloat4')
class SliderFloat4(SliderInput[float, Tuple[float, float, float, float]]):
"""A slider for 4 float values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0, 0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_float4(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderInt')
class SliderInt(SliderInput[int, int]):
"""A slider for an integer value.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = 0
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_int(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderInt2')
class SliderInt2(SliderInput[int, Tuple[int, int]]):
"""A slider for 2 integer values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_int2(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderInt3')
class SliderInt3(SliderInput[int, Tuple[int, int, int]]):
"""A slider for 3 integer values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_int3(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::SliderInt4')
class SliderInt4(SliderInput[int, Tuple[int, int, int, int]]):
"""A slider for 4 integer values.
If not disabled using the :attr:`no_input` property, the slider can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0, 0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_slider_int4(self.id, **dpg_args)
## Drag Input Boxes
# noinspection PyAbstractClass
[docs]@_register_item_type('mvAppItemType::DragFloat')
class DragFloat(DragInput[float, float]):
"""A drag input for a float value.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = 0.0
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_float(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragFloat2')
class DragFloat2(DragInput[float, Tuple[float, float]]):
"""A drag input for 2 float values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_float2(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragFloat3')
class DragFloat3(DragInput[float, Tuple[float, float, float]]):
"""A drag input for 3 float values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_float3(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragFloat4')
class DragFloat4(DragInput[float, Tuple[float, float, float, float]]):
"""A drag input for 4 float values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0.0, 0.0, 0.0, 0.0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_float4(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragInt')
class DragInt(DragInput[int, int]):
"""A drag input for an integer value.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = 0
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_int(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragInt2')
class DragInt2(DragInput[int, Tuple[int, int]]):
"""A drag input for 2 integer values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_int2(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragInt3')
class DragInt3(DragInput[int, Tuple[int, int, int]]):
"""A drag input for 3 integer values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_int3(self.id, **dpg_args)
[docs]@_register_item_type('mvAppItemType::DragInt4')
class DragInt4(DragInput[int, Tuple[int, int, int, int]]):
"""A drag input for 4 integer values.
If not disabled using the :attr:`no_input` property, the drag input can be CTRL+Clicked to turn it
into an input box for manual input of a value."""
_default_value = (0, 0, 0, 0)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_drag_int4(self.id, **dpg_args)
## Color
from dearpygui_obj.data import ColorRGBA, ConfigPropertyColorRGBA, import_color_from_dpg, export_color_to_dpg
[docs]@_register_item_type('mvAppItemType::ColorEdit4')
class ColorEdit(Widget, ItemWidgetMx, ValueWidgetMx[ColorRGBA]):
"""A color editing widget.
Clicking and draging the color square will copy the color to be applied on any other color widget."""
value: ColorRGBA #: The inputted color.
label: str = ConfigProperty()
no_alpha: bool = ConfigProperty() #: Don't include alpha channel.
no_picker: bool = ConfigProperty()
no_options: bool = ConfigProperty()
no_small_preview: bool = ConfigProperty()
no_inputs: bool = ConfigProperty()
no_tooltip: bool = ConfigProperty()
no_label: bool = ConfigProperty()
no_drag_drop: bool = ConfigProperty()
alpha_bar: bool = ConfigProperty()
alpha_preview: bool = ConfigProperty()
alpha_preview_half: bool = ConfigProperty()
display_rgb: bool = ConfigProperty()
display_hsv: bool = ConfigProperty()
display_hex: bool = ConfigProperty()
input_rgb: bool = ConfigProperty()
input_hsv: bool = ConfigProperty()
color_format: ColorFormatMode
@ConfigProperty()
def color_format(self) -> ColorFormatMode:
config = self.get_config()
if config['floats'] and not config['uint8']:
return ColorFormatMode.Float
return ColorFormatMode.UInt8
@color_format.getconfig
def color_format(self, value: ColorFormatMode):
if value == ColorFormatMode.UInt8:
return {'uint8':False, 'floats':True}
if value == ColorFormatMode.Float:
return {'uint8':True, 'floats':False}
raise ValueError('invalid color format mode')
def __init__(self, label: str = None, value: ColorRGBA = ColorRGBA(1, 0, 1), **config):
super().__init__(label=label, default_value=export_color_to_dpg(value), **config)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_color_edit4(self.id, **dpg_args)
def __get_value__(self) -> ColorRGBA:
return import_color_from_dpg(super().__get_value__())
def __set_value__(self, color: ColorRGBA) -> None:
super().__set_value__(export_color_to_dpg(color))
[docs]@_register_item_type('mvAppItemType::ColorPicker4')
class ColorPicker(Widget, ItemWidgetMx, ValueWidgetMx[ColorRGBA]):
"""A color picking widget.
Clicking and draging the color square will copy the color to be applied on any other color widget.
Right-click allows the style of the color picker to be changed."""
value: ColorRGBA #: The picked color.
label: str = ConfigProperty()
no_alpha: bool = ConfigProperty()
no_small_preview: bool = ConfigProperty()
no_inputs: bool = ConfigProperty()
no_tooltip: bool = ConfigProperty()
no_label: bool = ConfigProperty()
no_side_preview: bool = ConfigProperty()
alpha_bar: bool = ConfigProperty()
alpha_preview: bool = ConfigProperty()
alpha_preview_half: bool = ConfigProperty()
display_rgb: bool = ConfigProperty()
display_hsv: bool = ConfigProperty()
display_hex: bool = ConfigProperty()
picker_hue_bar: bool = ConfigProperty()
picker_hue_wheel: bool = ConfigProperty()
input_rgb: bool = ConfigProperty()
input_hsv: bool = ConfigProperty()
color_format: ColorFormatMode
@ConfigProperty()
def color_format(self) -> ColorFormatMode:
config = self.get_config()
if config['floats'] and not config['uint8']:
return ColorFormatMode.Float
return ColorFormatMode.UInt8
@color_format.getconfig
def color_format(self, value: ColorFormatMode):
if value == ColorFormatMode.UInt8:
return {'uint8':False, 'floats':True}
if value == ColorFormatMode.Float:
return {'uint8':True, 'floats':False}
raise ValueError('invalid color format mode')
def __init__(self, label: str = None, value: ColorRGBA = ColorRGBA(1, 0, 1), **config):
super().__init__(label=label, default_value=export_color_to_dpg(value), **config)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_color_picker4(self.id, **dpg_args)
def __get_value__(self) -> ColorRGBA:
return import_color_from_dpg(super().__get_value__())
def __set_value__(self, color: ColorRGBA) -> None:
super().__set_value__(export_color_to_dpg(color))
## Date/Time
from datetime import date, time
from dearpygui_obj.data import import_date_from_dpg, import_time_from_dpg
[docs]class DatePickerMode(Enum):
"""The picking mode shown in a :class:`.DatePicker`."""
Day = 0
Month = 1
Year = 2
[docs]@_register_item_type('mvAppItemType::DatePicker')
class DatePicker(Widget, ItemWidgetMx, ValueWidgetMx[date]):
"""A date picker widget.
Warning:
Setting the :attr:`value` property currently does not work. This is an issue with DPG 0.6.
Attempting to do so will raise a :class:`.NotImplementedError`.
"""
value: date
mode: DatePickerMode
@ConfigProperty(key='level')
def mode(self) -> DatePickerMode:
"""The current picking mode."""
config = self.get_config()
return DatePickerMode(config['level'])
@mode.getconfig
def mode(self, level: DatePickerMode):
return {'level' : level.value}
def __init__(self, **config):
super().__init__(**config)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_date_picker(self.id, **dpg_args)
def __get_value__(self) -> date:
return import_date_from_dpg(super().__get_value__())
def __set_value__(self, value: date) -> None:
raise NotImplementedError('not supported in Dear PyGui 0.6')
[docs]@_register_item_type('mvAppItemType::TimePicker')
class TimePicker(Widget, ValueWidgetMx[time]):
"""A time picker widget.
Warning:
Setting the :attr:`value` property currently does not work. This is an issue with DPG 0.6.
Attempting to do so will raise a :class:`.NotImplementedError`.
"""
format: TimePickerFormat
@ConfigProperty(key='hour24')
def mode(self) -> TimePickerFormat:
"""The current picking mode."""
config = self.get_config()
return TimePickerFormat(config['hour24'])
@mode.getconfig
def mode(self, format: TimePickerFormat):
return {'hour24' : format.value}
def __init__(self, **config):
super().__init__(**config)
def __setup_add_widget__(self, dpg_args) -> None:
dpgcore.add_time_picker(self.id, **dpg_args)
def __get_value__(self) -> time:
return import_time_from_dpg(super().__get_value__())
def __set_value__(self, value: time) -> None:
raise NotImplementedError('not supported in Dear PyGui 0.6')
__all__ = [
'InputText',
'InputFloat',
'InputFloat2',
'InputFloat3',
'InputFloat4',
'InputInt',
'InputInt2',
'InputInt3',
'InputInt4',
'SliderFloat',
'SliderFloat2',
'SliderFloat3',
'SliderFloat4',
'SliderInt',
'SliderInt2',
'SliderInt3',
'SliderInt4',
'DragFloat',
'DragFloat2',
'DragFloat3',
'DragFloat4',
'DragInt',
'DragInt2',
'DragInt3',
'DragInt4',
'ColorButton',
'ColorFormatMode',
'ColorEdit',
'ColorPicker',
'DatePickerMode',
'DatePicker',
]