Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 8 additions & 20 deletions src/toad/forms/editors.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,7 @@ def watch_feedback(self, text: str) -> None:
self.post_message(self.Feedback(text))


class BoolEditor(ValueEditor, FormCheckbox):
shows = (bool,)

class BoolEditor(ValueEditor, FormCheckbox, shows=(bool,)):
def control_arguments(self) -> dict[str, object]:
return {"value": bool(self.field.value)}

Expand Down Expand Up @@ -165,23 +163,19 @@ def paint(self) -> None:
self.value = self.value_text(self.field.value)


class IntEditor(LineEditor):
shows = (int,)
class IntEditor(LineEditor, shows=(int,)):
accepts = "integer"


class FloatEditor(LineEditor):
shows = (float,)
class FloatEditor(LineEditor, shows=(float,)):
accepts = "number"


class StrEditor(LineEditor):
shows = (str,)
class StrEditor(LineEditor, shows=(str,)):
accepts = "text"


class MultilineEditor(ValueEditor, UntintedTonePaint, FramedControl, TextArea):
shows = (Multiline,)
class MultilineEditor(ValueEditor, UntintedTonePaint, FramedControl, TextArea, shows=(Multiline,)):
height = Scalar.from_number(10)
padding = Spacing(0, 1, 0, 1)

Expand Down Expand Up @@ -255,9 +249,7 @@ def paint(self) -> None:
self.value = value if self.lists(value) else Select.NULL


class ChoicesEditor(SelectEditor):
shows = (AnnotationChoices,)

class ChoicesEditor(SelectEditor, shows=(AnnotationChoices,)):
def paint(self) -> None:
with self.prevent(Select.Changed):
self.set_options(self.options())
Expand All @@ -273,20 +265,16 @@ def options(self) -> Iterable[tuple[str, object]]:
return ((self.choices.label(choice), choice) for choice in self.choices.choices())


class EnumEditor(SelectEditor):
shows = (Enum,)

class EnumEditor(SelectEditor, shows=(Enum,)):
def options(self) -> Iterable[tuple[str, object]]:
members: type[Enum] = resolve_annotated(self.field.annotation) # type: ignore[assignment]
return ((format_enum_display(member), member) for member in members)


class OptionalEditor(ValueEditor, WidgetView, containers.VerticalGroup):
class OptionalEditor(ValueEditor, WidgetView, containers.VerticalGroup, shows=(Optional,)):
"""A field that may hold nothing: a box says whether it holds a value, and the
editor of that value is shown while it does."""

shows = (Optional,)

def bind_control(self) -> None:
self.holds_value = FormCheckbox("Set", value=self.field.value is not None)
self.member = ValueEditor.declared_for(self.field.member)
Expand Down
10 changes: 3 additions & 7 deletions src/toad/forms/form_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def paint_foreground(self):
return self.app.colours.colour(PrimaryColour)


class FieldView(WidgetView, containers.VerticalGroup, DeclaredViews):
class FieldView(DeclaredViews, WidgetView, containers.VerticalGroup):
"""One parameter of a form, shown the way its formbridge kind asks for."""

def __init__(self, field: DeclaredField) -> None:
Expand Down Expand Up @@ -84,11 +84,9 @@ def filter(self, term: str) -> bool:
raise NotImplementedError


class ValueView(FieldView):
class ValueView(FieldView, shows=(ParameterInfo,)):
"""A field with one value: its label, its help and the editor for its kind."""

shows = (ParameterInfo,)

CHANGED_MARK = " ●"

def __init__(self, field: DeclaredField) -> None:
Expand Down Expand Up @@ -132,11 +130,9 @@ def mark(self, changed: bool) -> None:
)


class GroupView(FocusWithinView, FieldView):
class GroupView(FocusWithinView, FieldView, shows=(DirectDataclassInfo,)):
"""A nested dataclass: a heading and the views of its fields."""

shows = (DirectDataclassInfo,)

padding = Spacing(0, 1, 0, 1)

@property
Expand Down
4 changes: 1 addition & 3 deletions src/toad/screens/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@
from toad.app_node import ToadNode


class SchemeEditor(SelectEditor, ToadNode):
class SchemeEditor(SelectEditor, ToadNode, shows=(SchemeName,)):
"""A colour scheme's name, picked from the schemes the running app has."""

shows = (SchemeName,)

def options(self) -> Iterable[tuple[str, object]]:
return ((name, name) for name in self.app.colours.schemes)

Expand Down
19 changes: 8 additions & 11 deletions src/toad/widgets/comms_command_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from toad.widgets.checkbox import Checkbox
from toad.forms.editors import MultilineEditor, ValueEditor
from toad.forms.form_view import InlineFormView
from formbridge.forms.declared_fields import Multiline
from formbridge.forms.declared_fields import DeclaredMetadata, Multiline
from toad.native_style import AutoWidth, EllipsisOverflow, SideMargin
from toad.screens.modal import CenteredScreen, DismissibleScreen, ModalPanel, ModalScreen, ShadedScreen
from toad.widget_actions import WidgetAction
Expand All @@ -32,7 +32,7 @@


@dataclass(eq=False)
class PreparedChoices(AnnotationChoices):
class PreparedChoices(AnnotationChoices, DeclaredMetadata):
"""The catalog last prepared for a draft, not another copy of its value."""
parameter: ChoiceTargetField

Expand All @@ -42,24 +42,22 @@ def choices(self):
def label(self, choice):
return next((label for label, value in self.parameter.choices if value == choice), 'Choose…')


ValueEditor.shown_by[PreparedChoices] = lambda field: ValueEditor.showing(
(*field.metadata(PreparedChoices).parameter.editor_declarations, AnnotationChoices)
)(field)
def declares(self):
"""The prepared parameter names its own editors first; any choices editor follows."""
yield from self.parameter.editor_declarations
yield from super().declares()


class CommandText(Multiline):
"""A command parameter of several lines; the command form shows it five rows tall."""


class CommandTextEditor(MultilineEditor):
shows = (CommandText,)
class CommandTextEditor(MultilineEditor, shows=(CommandText,)):
height = Scalar.from_number(5)


class CatalogField(ValueEditor, Button):
class CatalogField(ValueEditor, Button, shows=(ModelConfigOption,)):
"""The shared model selector edits the form's canonical draft value."""
shows = (ModelConfigOption,)

def bind_control(self):
self.paint()
Expand Down Expand Up @@ -244,7 +242,6 @@ def draft_changed(self, paths):
group='command-catalogs', exclusive=True)



def arguments(self):
return {name: self.state.get_resolved_value(name) for name in self.form.values}

Expand Down
3 changes: 1 addition & 2 deletions tests/textual/test_settings_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ class Shouted:
"""Declares text that is kept in capitals."""


class ShoutedEditor(editors.StrEditor):
shows = (Shouted,)
class ShoutedEditor(editors.StrEditor, shows=(Shouted,)):

def read(self, text: str) -> object:
return text.upper()
Expand Down