Ejemplo n.º 1
0
    def __init__(self):
        sender = LineBox(
            Edit(("header", "Sender email\n\n"), state.sender_email))
        recipient = LineBox(
            Edit(("header", "Recipient email\n\n"), state.recipient_email))
        grading_directory = LineBox(
            Edit(("header", "Grading directory\n\n"), state.grading_directory))
        subject = LineBox(Edit(("header", "Subject\n\n"), state.subject))
        message = LineBox(
            Edit(("header", "Message\n\n"), state.message, multiline=True))

        grid_elements = [
            {
                "sender_email": sender,
                "recipient_email": recipient
            },
            {
                "grading_directory": grading_directory,
                "subject": subject
            },
            {
                "message": message
            },
        ]

        super().__init__("Mail", grid_elements, mail)
Ejemplo n.º 2
0
    def build_unselected_widgets(self):
        cdict = juju.constraints_to_dict(self.md.get('constraints', ''))

        label = str(self.juju_machine_id)
        self.juju_machine_id_button = SecondaryButton(label,
                                                      self.show_pin_chooser)
        self.juju_machine_id_label = Text(label)
        self.cores_field = IntEdit('', str(cdict.get('cores', '')))
        connect_signal(self.cores_field, 'change', self.handle_cores_changed)
        memval = cdict.get('mem', '')
        if memval != '':
            memval = self._format_constraint(memval) / 1024
        self.mem_field = Edit('', str(memval))
        connect_signal(self.mem_field, 'change', self.handle_mem_changed)
        diskval = cdict.get('root-disk', '')
        if diskval != '':
            diskval = self._format_constraint(diskval) / 1024
        self.disk_field = Edit('', str(diskval))
        connect_signal(self.disk_field, 'change', self.handle_disk_changed)

        if self.show_pin:
            machine_id_w = self.juju_machine_id_button
        else:
            machine_id_w = self.juju_machine_id_label
        cols = [machine_id_w]
        for field in (self.cores_field, self.mem_field, self.disk_field):
            cols.append(AttrMap(field, 'string_input', 'string_input_focus'))
        cols.append(Text("placeholder"))
        self.unselected_columns = Columns(cols, dividechars=2)
        self.update_assignments()
        return self.unselected_columns
Ejemplo n.º 3
0
    def build_unselected_widgets(self):
        cdict = juju.constraints_to_dict(self.md.get('constraints', ''))

        self.juju_machine_id_button = MenuSelectButton(
            '{:20s}'.format(self.juju_machine_id), self.show_pin_chooser)
        self.juju_machine_id_label = Text("{:20s}".format(
            self.juju_machine_id))
        self.cores_field = IntEdit('', str(cdict.get('cores', '')))
        connect_signal(self.cores_field, 'change', self.handle_cores_changed)
        memval = cdict.get('mem', '')
        if memval != '':
            memval = memval / 1024
        self.mem_field = Edit('', str(memval))
        connect_signal(self.mem_field, 'change', self.handle_mem_changed)
        diskval = cdict.get('root-disk', '')
        if diskval != '':
            diskval = diskval / 1024
        self.disk_field = Edit('', str(diskval))
        connect_signal(self.disk_field, 'change', self.handle_disk_changed)

        if self.show_pin:
            machine_id_w = self.juju_machine_id_button
        else:
            machine_id_w = self.juju_machine_id_label
        cols = [
            machine_id_w, self.cores_field, self.mem_field, self.disk_field
        ]
        cols = [AttrMap(w, 'string_input', 'string_input_focus') for w in cols]
        cols.append(Text("placeholder"))
        self.unselected_columns = Columns(cols, dividechars=2)
        self.update_assignments()
        return self.unselected_columns
Ejemplo n.º 4
0
    def __init__(self):
        grading_directory = LineBox(
            Edit(("header", "Grading directory\n\n"), state.grading_directory))
        subdirectories = LineBox(
            Edit(("header", "Subdirectories\n\n"), state.subdirectories))
        assignment_type = RadioGroup("Assignment type", AssignmentType,
                                     state.assignment_type)
        deadline = LineBox(Edit(("header", "Deadline\n\n"), state.deadline))
        assignment_sname = LineBox(
            Edit(("header", "Assignment short name\n\n"),
                 state.assignment_sname))
        assignment_lname = LineBox(
            Edit(("header", "Assignment long name\n\n"),
                 state.assignment_lname))

        grid_elements = [
            {
                "grading_directory": grading_directory,
                "subdirectories": subdirectories
            },
            {
                "assignment_type": assignment_type,
                "deadline": deadline
            },
            {
                "assignment_sname": assignment_sname,
                "assignment_lname": assignment_lname
            },
        ]

        super().__init__("Grade", grid_elements, grade)
Ejemplo n.º 5
0
 def __init__(self):
     # self.caption = AttrMap(
     #         Text(
     #             ('caption', self.caption_text), align='center'
     #         ),
     #         'blackongrey'
     # )
     self.caption = Text(('caption', self.caption_text), align='center')
     self.inputbox_a = Padding(AttrMap(
         Edit(multiline=False, mask=self.mask), 'inputfield'),
                               align='center',
                               width=24)
     self.divider = Padding(Divider(' '), align='center')
     self.inputbox_b = Padding(AttrMap(
         Edit(multiline=False, mask=self.mask), 'inputfield'),
                               align='center',
                               width=24)
     self.innerbox = AttrMap(
         LineBox(Pile([self.inputbox_a, self.divider, self.inputbox_b])),
         'blackongrey')
     # scratchpad = Text('<enter>')
     self.button = Button('OK', on_press=self._ok_button)
     self.button_wrap = Padding(AttrMap(self.button, 'button.normal',
                                        'button.focus'),
                                align='center',
                                width=15)
Ejemplo n.º 6
0
    def __init__(self, submit_cb, back_cb, error=None):
        self.submit_cb = submit_cb
        self.prev_screen = back_cb
        self.error = error

        self.email = Edit()
        self.password = Edit(mask='*')
        self.twofa = Edit()
        # can't use IntEdit because it precludes leading zeros
        self.twofa.valid_char = lambda ch: ch in '0123456789'

        super().__init__()
Ejemplo n.º 7
0
    def _build_fields(self):
        self.email = Edit()
        self.password = Edit(mask='*')
        self.twofa = Edit()
        # can't use IntEdit because it precludes leading zeros
        self.twofa.valid_char = lambda ch: ch in '0123456789'

        return Pile([
            Color.string_input(self.email),
            Padding.line_break(""),
            Color.string_input(self.password),
            Padding.line_break(""),
            Color.string_input(self.twofa)
        ])
Ejemplo n.º 8
0
    def __init__(self):
        grading_directory = LineBox(Edit(("header", "Grading directory\n\n"), state.grading_directory))
        grader_name = LineBox(Edit(("header", "Grader's name\n\n"), state.grader_name))
        group_number = LineBox(IntEdit(("header", "Group number\n\n"), state.group_number))
        team_type = RadioGroup("Team type", TeamType, state.team_type)
        username = LineBox(Edit(("header", "Username\n\n"), ""))
        password = LineBox(Edit(("header", "Password\n\n"), "", mask="*"))

        grid_elements = [
            {"grading_directory": grading_directory, "grader_name": grader_name},
            {"group_number": group_number, "team_type": team_type},
            {"username": username, "password": password},
        ]

        super().__init__("Clone", grid_elements, clone)
Ejemplo n.º 9
0
    def __init__(self):
        grading_directory = LineBox(
            Edit(("header", "Grading directory\n\n"), state.grading_directory))
        assignment_sname = LineBox(
            Edit(("header", "Assignment short name\n\n"),
                 state.assignment_sname))

        grid_elements = [
            {
                "grading_directory": grading_directory,
                "assignment_sname": assignment_sname
            },
        ]

        super().__init__("Push", grid_elements, push)
Ejemplo n.º 10
0
 def get_widget(self):
     if isinstance(self.value, str):
         return AttrMap(Edit('', self.value), 'editable')
     elif isinstance(self.value, bool):
         return CheckBox('', self.value)
     else:
         return Text("Unknown field for {}".format(str(type(self.value))))
Ejemplo n.º 11
0
  def __init__(self, edit_text, strike=False, new=False):
 
    self.strikethrough = strike
    self.new_expan = new

    # Spacing strings
    self.leading_space = '   '
    self.leading_char = '- '
    self.leading_STRIKE = 'x '

    # Default color specs
    self.text_attr = AttrSpec('h6', '')
    self.text_STRIKE = AttrSpec('h6, strikethrough', '')
    self.focus_attr = AttrSpec('h6, bold', '')
    self.focus_STRIKE = AttrSpec('h6, bold, strikethrough', '')

    if not self.strikethrough:
      caption = self.leading_space + self.leading_char
      attr = self.text_attr
      attr_focus = self.focus_attr
    else:
      caption = self.leading_space + self.leading_STRIKE
      attr = self.text_STRIKE
      attr_focus = self.focus_STRIKE

    self.edit = Edit(caption, edit_text, wrap='clip')
    self.map = AttrMap(self.edit, attr_map=attr, focus_map=attr_focus)
    self.fill = Filler(self.map)

    super().__init__(self.map)
Ejemplo n.º 12
0
    def create_interface(self):
        self.screen = Screen()
        self.screen.start()

        self.screen.register_palette([
            ("title", "white", "dark blue", "standout"),
            ("line", "light gray", "black"),
            ("help", "white", "dark blue")]
        )

        self.body = ListBox(SimpleListWalker([]))
        self.lines = self.body.body

        self.title = Text(MAIN_TITLE)
        self.header = AttrWrap(self.title, "title")

        self.help = AttrWrap(
            Text(HELP_STRINGS["main"]),
            "help"
        )

        self.input = Edit(caption="%s> " % self.ircchannel)
        self.footer = Pile([self.help, self.input])

        self.top = Frame(self.body, self.header, self.footer)
Ejemplo n.º 13
0
    def __init__(self,
                 prompt,
                 content,
                 done_signal_handler,
                 cursor_position=None):
        """
        Initializes editor, connects 'done' signal.

        When pressing 'enter' twice the `submit` method is called, which by
        default calls `emit_done_signal` with the text that has been
        introduced.

        When pressing 'esc' the `cancel` method is called, which by default
        calls `emit_done_signal` with no arguments.

        The subclasses must call the `_wrap` method with the editor widgets
        and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to
        `urwid.WidgetWrap.__init__` with the wrapped widget.
        """
        caption = _(u'{0} (Enter key twice to validate, '
                    u'Esc or Ctrl-C to cancel) \n>> ').format(prompt)
        if content:
            content += ' '
        self.content = content
        self.editor = Edit(caption=caption,
                           edit_text=content,
                           edit_pos=cursor_position)
        self.last_key = None

        connect_signal(self, 'done', done_signal_handler)
Ejemplo n.º 14
0
    def build_widgets(self):
        self.editbox = Edit(caption=('text', "Search Charm Store: "))

        connect_signal(self.editbox, 'change', self.handle_edit_changed)

        return Padding(AttrMap(self.editbox, 'filter', 'filter_focus'),
                       left=2,
                       right=2)
Ejemplo n.º 15
0
 def __init__(self, caption=None, default=None, **kwargs):
     if caption is None:
         caption = ""
     self._edit = Edit(caption=caption, **kwargs)
     if default is not None:
         self._edit.set_edit_text(default)
     self.error = None
     super().__init__(self._edit)
Ejemplo n.º 16
0
 def render_component(self, props):
     self.edit = Edit(caption='Todo: ', edit_text='')
     self.button = Button('Add Todo')
     return Columns([
         (1, Text('[')),
         self.edit,
         (1, Text(']')),
         (18, self.button),
     ])
Ejemplo n.º 17
0
    def __init__(self,
                 choice_callback=None,
                 command_callback=None,
                 help_callback=None):

        self.palette = [
            ('brick', 'light red', 'black'),
            ('rubble', 'yellow', 'black'),
            ('wood', 'light green', 'black'),
            ('concrete', 'white', 'black'),
            ('stone', 'light cyan', 'black'),
            ('marble', 'light magenta', 'black'),
            ('jack', 'dark gray', 'white'),
            ('msg_info', 'white', 'black'),
            ('msg_err', 'light red', 'black'),
            ('msg_debug', 'light green', 'black'),
        ]

        self.choice_callback = choice_callback
        self.command_callback = command_callback
        self.help_callback = help_callback

        self.screen = None
        self.loop = None
        self.called_loop_stop = False
        self.reactor_stop_fired = False

        self.quit_flag = False
        self.edit_msg = "Make selection ('q' to quit): "
        self.roll_list = SimpleListWalker([])
        self.game_log_list = SimpleListWalker([])
        self.choices_list = SimpleListWalker([])

        self.state_text = SimpleListWalker([Text('Connecting...')])

        self.edit_widget = Edit(self.edit_msg)
        self.roll = ListBox(self.roll_list)
        self.game_log = ListBox(self.game_log_list)
        self.choices = ListBox(self.choices_list)
        self.state = ListBox(self.state_text)

        self.left_frame = Pile([
            LineBox(self.state),
            (13, LineBox(self.choices)),
        ])

        self.right_frame = Pile([LineBox(self.game_log), LineBox(self.roll)])

        self.state.set_focus(len(self.state_text) - 1)

        self.columns = Columns([('weight', 0.75, self.left_frame),
                                ('weight', 0.25, self.right_frame)])
        self.frame_widget = Frame(footer=self.edit_widget,
                                  body=self.columns,
                                  focus_part='footer')

        self.exc_info = None
Ejemplo n.º 18
0
    def __init__(self, edit_changed_cb, label="", info_text=""):
        self.label = Text(label)
        self.info_text = Text(info_text)
        self.editbox = Edit(caption=('text', "Filter: "))
        connect_signal(self.editbox, 'change', edit_changed_cb)

        w = Pile([
            Columns([AttrMap(self.editbox, 'filter', 'filter_focus')])
            # self.info_text  # -- WORKAROUND for issue #194
        ])
        super().__init__(w)
Ejemplo n.º 19
0
 def editable(self, yes):
     if self._editable == yes:
         return
     self._editable = yes
     if yes:
         self._content = Edit(caption="tags:", edit_text=self._content.get_text()[0])
         self._update()
         self._root.focus_position = 1
     else:
         self._content = Text(self._content.get_edit_text())
         self._update()
Ejemplo n.º 20
0
    def __init__(self, prompt, content, done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(
            u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        widgets = [self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)

        self.__super.__init__(w)
Ejemplo n.º 21
0
    def __init__(self, edit_changed_cb):
        self.label = Text("")
        self.info_text = Text("")
        self.editbox = Edit()
        connect_signal(self.editbox, 'change',
                       edit_changed_cb)

        w = Pile([Columns([('pack', self.label),
                           AttrMap(self.editbox,
                                   'filter', 'filter_focus')])
                  # self.info_text  # -- WORKAROUND for issue #194
                  ])
        super().__init__(w)
Ejemplo n.º 22
0
    def __init__(self,
                 height,
                 directory=".",
                 file="",
                 attr=(None, None),
                 show_hidden=False):
        """
        height -- height of the directory list and the file list
        directory, file -- default selection
        attr -- (inner selectable widgets, selected widgets)
        show_hidden -- If True, hidden files are shown by default.
        """

        self.directory = abspath(directory)
        self.file = ""
        self.attr = attr
        self.height = height
        self.show_hidden = show_hidden

        # Create dummy widgets for directory and file display:
        self.dir_widget = AttrWrap(
            BoxAdapter(ListBox([self._blank]), self.height), self.attr[0])
        self.file_widget = AttrWrap(
            BoxAdapter(ListBox([self._blank]), self.height), self.attr[0])

        columns = Columns([self.dir_widget, self.file_widget], 1)

        # Selection widget:
        self.select_widget = AttrWrap(Edit("", ""), self.attr[0], self.attr[1])

        # Buttons and checkbox:
        button_widgets = [
            AttrWrap(Button(button, self._action), attr[0], attr[1])
            for button in ["OK", "Cancel"]
        ]
        button_grid = GridFlow(button_widgets, 12, 2, 1, 'center')

        button_cols = Columns([
            CheckBox(self.SHOW_HIDDEN_TEXT, self.show_hidden, False,
                     self._toggle_hidden), button_grid
        ])

        self.outer_widget = Pile([
            columns, self._blank,
            Text(self.SELECTION_TEXT), self.select_widget, self._blank,
            button_cols
        ])

        self.update_widgets()

        WidgetWrap.__init__(self, self.outer_widget)
Ejemplo n.º 23
0
    def __init__(self, done_handler, note=None):
        self.modes = ['title', 'tags', 'text']
        self.mode = self.modes[0]
        self.note = note
        if note is None:
            self.title = ''
            self.tags = ''
            self.text = ''
        else:
            self.title = note.title
            self.tags = note.formatted_tags()
            self.text = note.text

        self.editor = Edit(u'title :: ', self.title)
        connect_signal(self, 'done', done_handler)
        WidgetWrap.__init__(self, self.editor)
Ejemplo n.º 24
0
    def __init__(self, prompt, content, done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(
            u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        self.counter = len(content)
        self.counter_widget = Text(str(self.counter))

        widgets = [('fixed', 4, self.counter_widget), self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)
        connect_signal(self.editor, 'change', self.update_counter)

        self.__super.__init__(w)
Ejemplo n.º 25
0
    def __init__(self, content, default, tooltip, left_margin, source=None):
        """
        General Edit Field

        Args:
            content: text of the editbox
            default: default value of the editbox
            tooltip: tooltip of the editbox
            left_margin: left_margin of the editbox
            source: there this item is from for value reference
        """
        text = u" *  " + content + u": "
        self.core = Edit(('editcp', ""), default)
        self.source = source
        self.widget = Pile([
            Text(text),
            Padding(AttrWrap(self.core, 'editbx', 'editfc'), left=4),
            Padding(Text(tooltip), left=4)
        ])
        super().__init__(self.widget, left=2 + left_margin - 4, right=2)
Ejemplo n.º 26
0
  def __init__(self, tag_index, tag_text, new=False):
    self.new_tag = new
    
    op_char = tag_text[0]
    if op_char == 'o':
      self.strikethrough = False
    elif op_char == 'x':
      self.strikethrough = True

    tag_text = tag_text.lstrip(op_char)
    self.tag_index = tag_index
    self.tag_text = tag_text

    # Default color specs
    self.index_attr = AttrSpec('h11', '')
    self.index_STRIKE = AttrSpec('h11, strikethrough', '')
    self.text_attr = AttrSpec('', '')
    self.text_STRIKE = AttrSpec(', strikethrough', '')
    self.focus_attr = AttrSpec(', bold', '')
    self.focus_STRIKE = AttrSpec(', bold, strikethrough', '')

    # Build widget stack
    self.edit = Edit(
        caption=self.build_caption(),
        edit_text=self.tag_text,
        multiline=False,
        wrap ='clip')
    if not self.strikethrough:
      self.tag_map = AttrMap(
          self.edit,
          attr_map=self.text_attr,
          focus_map=self.focus_attr)
    else:
      self.tag_map = AttrMap(
          self.edit,
          attr_map=self.text_STRIKE,
          focus_map=self.focus_STRIKE)
    self.tag_fill = Filler(self.tag_map, 'top')

    super().__init__(self.tag_map)
Ejemplo n.º 27
0
 def __init__(self, caption, **kwargs):
     self._edit = Edit(caption=caption, **kwargs)
     super().__init__(self._edit)
Ejemplo n.º 28
0
def run(host, port):
    """
    Start a websocket client and a terminal UI to interact with it.
    """
    # connection state
    channels = []
    bound_channel = None
    ws = None

    # UI state
    lines = ['example text\n']
    output = Text(lines)
    input_field = Edit('>> ')
    input_state = COMMAND_READ
    widget = Frame(Filler(output, 'top'), footer=input_field)
    widget.focus_position = 'footer'

    # event wiring
    event_loop = AsyncioEventLoop(loop=loop)
    input_cb = None

    def write(msg):
        """
        Show an additional line of text.
        """
        lines.append(msg + '\n')
        output.set_text(lines)

    def prompt_for_password(msg):
        """
        Change prompt to password prompt. Return a future for the typed password.
        """
        nonlocal input_cb, input_state
        input_cb = loop.create_future()
        input_state = PASSWORD_READ
        input_cb.add_done_callback(_password_done)
        input_field.set_mask('*')
        input_field.set_caption(msg)
        return input_cb

    def _password_done(_):
        nonlocal input_state
        input_field.set_mask(None)
        input_state = COMMAND_READ

    def accept_input(key):
        """
        Process typed lines of text. Dispatches to password prompt or command prompt
        as needed.
        """
        if key == 'enter':
            if input_state == PASSWORD_READ:
                input_cb.set_result(input_field.edit_text)
            elif input_state == COMMAND_READ:
                cmd_dispatch(input_field.edit_text)
            input_field.set_edit_text('')

    def update_channels(new_channels):
        """
        Receive channel data.
        """
        nonlocal channels, bound_channel
        channels = new_channels
        if len(channels) == 1:
            bound_channel = channels[0]
            write(f'bound console to channel "{bound_channel}"')
        else:
            write(f'bot is in these channels: {", ".join(channels)}')

    async def ws_dispatch():
        """
        Handle websocket messages.
        """
        nonlocal ws
        ws = await websockets.connect(f'ws://{host}:{port}')
        while True:
            try:
                msg = json.loads(await ws.recv())
                if msg['type'] == SEND_PASSWORD:
                    loop.create_task(
                        ws.send(await prompt_for_password("Server password:"******"dispatching {repr(command)}")
        nonlocal bound_channel
        if not ws:
            write('Not connected')
            return
        parts = command.split()

        if not parts:
            print_help()

        command_part = parts[0].lower()
        if command_part[0] == '/':
            command_part = command_part[1:]
        args = parts[1:]
        if command_part == 'help':
            print_help()
        elif command_part == 'sendcmd':
            if not bound_channel:
                write(
                    'there is not a bound channel! use `/channel <channel>` to bind one!'
                )
            elif not args:
                write(
                    'you must provide a command to run to /sendcmd, ex: /sendcmd help'
                )
            else:
                loop.create_task(
                    ws.send(
                        json.dumps({
                            'type': RUN_COMMAND,
                            'channel': bound_channel,
                            'command': args[0],
                            'args': args[1:],
                            'silent': True,
                        })))
        elif command_part == 'chat':
            if not bound_channel:
                write(
                    'there is not a bound channel! use `/channel <channel>` to bind one!'
                )
            else:
                loop.create_task(
                    ws.send(
                        json.dumps({
                            'type': SEND_PRIVMSG,
                            'channel': bound_channel,
                            'message': ' '.join(args),
                        })))

        elif command_part == 'channel':
            if not channels:
                write(
                    'the bot is not currently in any channels, please have the bot join at least one than relaunch this console'
                )
            elif not args:
                write(
                    f'the bot is currently in these channels: {", ".join(channels)}\ndo `/channel <channel>` to bind this channel to one'
                )
            elif args[0] not in channels:
                write(f'the bot is not currently in "{args[0]}"')
            else:
                bound_channel = args[0]
        elif command_part == 'quit':
            raise ExitMainLoop()

        else:
            write(f"Unrecognized command {repr(command_part)}")

    event_loop.alarm(0, lambda: loop.create_task(ws_dispatch()))
    mainloop = MainLoop(widget,
                        event_loop=event_loop,
                        unhandled_input=accept_input)
    mainloop.run()
Ejemplo n.º 29
0
from widget import SelectableText
from widget import SSHCheckBox
from widget import SearchableFrame

from urwid import Edit
from urwid import Text
from urwid import Columns
from urwid import MainLoop
from urwid import AttrMap
from urwid import LineBox
from urwid import ListBox
from urwid import SimpleFocusListWalker


SEARCH_EDIT = Edit('search: ')
HEADER = AttrMap(SEARCH_EDIT, 'header')

SESSION_NAME_PREFIX = "gz-"

SELECTED_HOSTS = []
GROUP_WIDGETS = []
HOST_WIDGETS = collections.OrderedDict()


def create_tmux_command():
    session = create_session_name()
    commands = [
        "tmux new-session -s %s -d -x 2000 -y 2000" % session,
        "tmux send-keys -t %s 'ssh %s' C-m" % (session, SELECTED_HOSTS[0])
    ]
Ejemplo n.º 30
0
    return model


def default_leaf(model, f, active):
    raise Exception(f'Unexpected leaf: {model}')


LEAF_DATE = defaultdict(
    lambda: default_leaf, {
        TEXT:
        lambda model, f, active: Text(model[VALUE]),
        EDIT:
        lambda model, f, active: f(
            wire(
                model,
                Edit(caption=label(model[LABEL] + ': '),
                     edit_text=model[VALUE] or ''))),
        FLOAT:
        lambda model, f, active: f(
            wire(
                model,
                Float(caption=label(model[LABEL] + ': '),
                      state=model[VALUE],
                      minimum=model[LO],
                      maximum=model[HI],
                      dp=model[DP],
                      units=model[UNITS]))),
        INTEGER:
        lambda model, f, active: f(
            wire(
                model,
                Integer(caption=label(model[LABEL] + ': '),