#-----------------------------------------------------------------------------
# Copyright (c) 2012 - 2023, Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
''' Various kinds of input widgets and form controls.
'''
#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
from __future__ import annotations
import logging # isort:skip
log = logging.getLogger(__name__)
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# Standard library imports
from math import inf
# Bokeh imports
from ...core.has_props import abstract
from ...core.properties import (
Bool,
Color,
ColorHex,
Dict,
Either,
Enum,
Float,
Instance,
Int,
Interval,
List,
NonNegative,
Null,
Nullable,
Override,
Positive,
Readonly,
Required,
Seq,
String,
Tuple,
)
from ..formatters import TickFormatter
from ..ui import Tooltip
from .widget import Widget
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
__all__ = (
'AutocompleteInput',
'Checkbox',
'ColorMap',
'ColorPicker',
'FileInput',
'InputWidget',
'MultiChoice',
'MultiSelect',
'NumericInput',
'PasswordInput',
'Select',
'Spinner',
'Switch',
'TextAreaInput',
'TextInput',
)
#-----------------------------------------------------------------------------
# Dev API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------
[docs]class Spinner(NumericInput):
''' Numeric Spinner input widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
value_throttled = Readonly(Either(Null, Float, Int), help="""
Value reported at the end of interactions.
""")
mode = Override(default="float")
step = Interval(Float, start=1e-16, end=inf, default=1, help="""
The step added or subtracted to the current value.
""")
page_step_multiplier = Interval(Float, start=0, end=inf, default=10, help="""
Defines the multiplication factor applied to step when the page up and page
down keys are pressed.
""")
wheel_wait = Either(Int, Float, default=100, help="""
Defines the debounce time in ms before updating `value_throttled` when the
mouse wheel is used to change the input.
""")
@abstract
class ToggleInput(Widget):
""" Base class for toggleable (boolean) input widgets. """
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
active = Bool(default=False, help="""
The state of the widget.
""")
[docs]class Checkbox(ToggleInput):
""" A checkbox widget. """
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
label = String(default="", help="""
The label next to the checkbox.
""")
[docs]class Switch(ToggleInput):
""" A checkbox-like widget. """
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
width = Override(default=32)
class TextLikeInput(InputWidget):
''' Base class for text-like input widgets.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
value = String(default="", help="""
Initial or entered text value.
Change events are triggered whenever <enter> is pressed.
""")
value_input = String(default="", help="""
Initial or current value.
Change events are triggered whenever any update happens, i.e. on every
keypress.
""")
placeholder = String(default="", help="""
Placeholder for empty input field.
""")
max_length = Nullable(Int, help="""
Max count of characters in field
""")
[docs]class TextInput(TextLikeInput):
''' Single-line input widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
prefix = Nullable(String, help="""
An optional string prefix to display before the input. This is useful to
indicate e.g. a variable the entered value will be assigned to.
""")
suffix = Nullable(String, help="""
An optional string suffix to display after the input. This is useful to
indicate e.g. the units of measurement of the entered value.
""")
[docs]class TextAreaInput(TextLikeInput):
''' Multi-line input widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
cols = Int(default=20, help="""
Specifies the width of the text area (in average character width). Default: 20
""")
rows = Int(default=2, help="""
Specifies the height of the text area (in lines). Default: 2
""")
max_length = Override(default=500)
[docs]class Select(InputWidget):
''' Single-select widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
options = Either(List(Either(String, Tuple(String, String))),
Dict(String, List(Either(String, Tuple(String, String)))), help="""
Available selection options. Options may be provided either as a list of
possible string values, or as a list of tuples, each of the form
``(value, label)``. In the latter case, the visible widget text for each
value will be corresponding given label. Option groupings can be provided
by supplying a dictionary object whose values are in the aforementioned
list format
""").accepts(List(Either(Null, String)), lambda v: [ "" if item is None else item for item in v ])
value = String(default="", help="""
Initial or selected value.
""").accepts(Null, lambda _: "")
[docs]class MultiSelect(InputWidget):
''' Multi-select widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
options = List(Either(String, Tuple(String, String)), help="""
Available selection options. Options may be provided either as a list of
possible string values, or as a list of tuples, each of the form
``(value, label)``. In the latter case, the visible widget text for each
value will be corresponding given label.
""")
value = List(String, help="""
Initial or selected values.
""")
size = Int(default=4, help="""
The number of visible options in the dropdown list. (This uses the
``select`` HTML element's ``size`` attribute. Some browsers might not
show less than 3 options.)
""")
[docs]class MultiChoice(InputWidget):
''' MultiChoice widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
options = List(Either(String, Tuple(String, String)), help="""
Available selection options. Options may be provided either as a list of
possible string values, or as a list of tuples, each of the form
``(value, label)``. In the latter case, the visible widget text for each
value will be corresponding given label.
""")
value = List(String, help="""
Initial or selected values.
""")
delete_button = Bool(default=True, help="""
Whether to add a button to remove a selected option.
""")
max_items = Nullable(Int, help="""
The maximum number of items that can be selected.
""")
option_limit = Nullable(Int, help="""
The number of choices that will be rendered in the dropdown.
""")
search_option_limit = Nullable(Int, help="""
The number of choices that will be rendered in the dropdown
when search string is entered.
""")
placeholder = Nullable(String, help="""
A string that is displayed if not item is added.
""")
solid = Bool(default=True, help="""
Specify whether the choices should be solidly filled.""")
[docs]class ColorPicker(InputWidget):
''' Color picker widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
color = ColorHex(default='#000000', help="""
The initial color of the picked color (named or hexadecimal)
""")
[docs]class ColorMap(InputWidget):
''' Color map picker widget.
'''
# explicit __init__ to support Init signatures
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
value = Required(String, help="""
""")
items = Required(Seq(Tuple(String, Seq(Color))), help="""
""")
swatch_width = NonNegative(Int, default=100, help="""
""")
swatch_height = NonNegative(Int, default=20, help="""
""")
ncols = Positive(Int, default=1, help="""
""")
#-----------------------------------------------------------------------------
# Private API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------