]> skyeroc.xyz Git - obs-ctl/commitdiff
Continue restructuring
authorsbkelley <sb24kelley@gmail.com>
Sun, 30 Nov 2025 19:42:04 +0000 (14:42 -0500)
committersbkelley <sb24kelley@gmail.com>
Sun, 30 Nov 2025 19:42:04 +0000 (14:42 -0500)
12 files changed:
src/obs_ctl/__init__.py
src/obs_ctl/data/layout.tcss
src/obs_ctl/interface/__init__.py [new file with mode: 0644]
src/obs_ctl/interface/element/__init__.py [new file with mode: 0644]
src/obs_ctl/interface/element/bool_control.py [new file with mode: 0644]
src/obs_ctl/interface/element/text_readout.py [new file with mode: 0644]
src/obs_ctl/interface/message.py [new file with mode: 0644]
src/obs_ctl/interface/molecule/__init__.py [new file with mode: 0644]
src/obs_ctl/interface/molecule/record_controls.py [new file with mode: 0644]
src/obs_ctl/widget/__init__.py [deleted file]
src/obs_ctl/widget/element/bool_control.py [deleted file]
src/obs_ctl/widget/element/text_readout.py [deleted file]

index 440cccd8e8156ce785cc8524e1cb5e9bf5e494b6..a4326e96a6bb5b4f8eccfd66bc496454e1b82aea 100644 (file)
@@ -11,10 +11,11 @@ from textual.widgets import Footer, Header, Label, Placeholder, TabbedContent, T
 from textual.css.query import NoMatches
 
 from . import log, data
-from .widget import OBSSettingsPane
+from .interface import OBSSettingsPane
 
-from .widget.element.bool_control import BoolControl
-from .widget.element.text_readout import TextReadout
+from .interface.element.bool_control import BoolControl
+from .interface.element.text_readout import TextReadout
+from .interface import RecordControls
 
 logger = log.getLogger(__name__)
 obs_req_client = obs.ReqClient()
@@ -70,10 +71,11 @@ class OBSCtlApp(App):
         with ScrollableContainer(id="content_container"):
             with Vertical(id="blocks_v_container", classes="blocks_containers"):
                 with Horizontal(id="blocks_h_container1", classes="blocks_h_containers"):
-                    with Grid(id="controls_container", classes="blocks gridblocks"):
-                        yield BoolControl(False, label="Recording", id="record_control", classes="controls")
-                        yield BoolControl(False, label="Paused", true_label="Pause", false_label="Unpause", swap_red=True, id="pause_control", classes="controls")
-                        yield BoolControl(False, label="Streaming", id="stream_control", classes="controls")
+                    yield RecordControls(id="record_controls")
+                    # with Grid(id="controls_container", classes="blocks gridblocks"):
+                    #     yield BoolControl(False, label="Recording", id="record_control", classes="controls")
+                    #     yield BoolControl(False, label="Paused", true_label="Pause", false_label="Unpause", swap_red=True, id="pause_control", classes="controls")
+                    #     yield BoolControl(False, label="Streaming", id="stream_control", classes="controls")
                     with TabbedContent(id="settings_container", classes="blocks"):
                         with TabPane("OBS Settings", id="settings-tab"):
                             yield OBSSettingsPane(id="settings-content")
@@ -93,9 +95,8 @@ class OBSCtlApp(App):
                         yield TextReadout("Encdng frames dropped", "-/- (-.-%)", id="encoding_lag", classes="stats")
 
 
-    @on(BoolControl.SetFalse, "#stream_control")
+    @on(RecordControls.StreamStopped, "#record_controls",)
     def stream_off(self, message):
-        logger.debug(f"Stop message rcv'd from {message.control}")
         try:
             obs_req_client.stop_stream()
         except obs_error.OBSSDKRequestError as err:
@@ -104,9 +105,9 @@ class OBSCtlApp(App):
             else:
                 raise
 
-    @on(BoolControl.SetTrue, "#stream_control")
+
+    @on(RecordControls.StreamStarted, "#record_controls")
     def stream_on(self, message):
-        logger.debug("Stream Started message rcv'd")
         try:
             obs_req_client.start_stream()
         except obs_error.OBSSDKRequestError as err:
@@ -115,20 +116,9 @@ class OBSCtlApp(App):
             else:
                 raise
 
-    @on(BoolControl.SetFalse, "#record_control")
-    def record_off(self, message):
-        logger.debug("Record Stopped message rcv'd")
-        try:
-            obs_req_client.stop_record()
-        except obs_error.OBSSDKRequestError as err:
-            if err.code == 501:
-                logger.debug("Record already stopped.")
-            else:
-                raise
 
-    @on(BoolControl.SetTrue, "#record_control")
+    @on(RecordControls.RecordStarted, "#record_controls")
     def record_on(self, message):
-        logger.debug("Record Started message rcv'd")
         try:
             obs_req_client.start_record()
         except obs_error.OBSSDKRequestError as err:
@@ -138,7 +128,19 @@ class OBSCtlApp(App):
                 raise
 
 
-    @on(BoolControl.SetTrue, "#pause_control")
+    @on(RecordControls.RecordStopped, "#record_controls")
+    def record_off(self, message):
+        logger.debug("Record Stopped message rcv'd")
+        try:
+            obs_req_client.stop_record()
+        except obs_error.OBSSDKRequestError as err:
+            if err.code == 501:
+                logger.debug("Record already stopped.")
+            else:
+                raise
+
+
+    @on(RecordControls.RecordPaused, "#record_controls")
     def pause_on(self, message):
         logger.debug("Record Paused message rcv'd")
         try:
@@ -150,7 +152,7 @@ class OBSCtlApp(App):
                 raise
 
 
-    @on(BoolControl.SetFalse, "#pause_control")
+    @on(RecordControls.RecordUnpaused, "#pause_control")
     def pause_off(self, message):
         logger.debug("Record Unpaused message rcv'd")
         try:
index ef7d44ee27d70cc3302996c812b428b9be58ba0e..e0dbb185b8bc0890020298309879749a85eeaceb 100644 (file)
@@ -35,6 +35,9 @@
     min-height:8;
 }
 
+RecordControls {
+}
+
 BoolControl {
     background:$surface;
     border:blank;
diff --git a/src/obs_ctl/interface/__init__.py b/src/obs_ctl/interface/__init__.py
new file mode 100644 (file)
index 0000000..2015550
--- /dev/null
@@ -0,0 +1,56 @@
+from textual.app import App, ComposeResult
+from textual.containers import Horizontal, VerticalScroll, Grid, Container
+from textual.message import Message
+from textual.reactive import reactive
+from textual.widgets import Label, RadioButton, Button, Input
+from textual.widget import Widget
+from textual.css import query
+
+from .message import MSGBase
+from .molecule import RecordControls
+from .. import log
+
+
+
+logger = log.getLogger(__name__)
+
+class OBSSettingsPane(VerticalScroll):
+    DEFAULT_CSS = """
+    .obssettingspane--input {
+        width:1fr;
+    }
+    Grid {
+        grid-size:2 1;
+        grid-columns:21 1fr;
+        Label {
+            width:1fr;
+            text-align:right;
+            padding-right:1;
+        }
+    }
+    """
+    COMPONENT_CLASSES = {
+        "obssettingspane--input",
+    }
+    record_path: reactive[str] = reactive("")
+    class RecordPathChanged(Message):
+        control: "OBSSettingsPane" = None
+        record_path: str = None
+        def __init__(self, ctrl, path):
+            super().__init__()
+            self.control = ctrl
+            self.record_path = path
+
+    def compose(self):
+        with Grid():
+            yield Label("Record path:")
+            yield Input("path", id="input_record_path", classes="obssettingspane--input", compact=True)
+    
+    def on_input_submitted(self, event:Input.Submitted):
+        self.set_reactive(OBSSettingsPane.record_path, event.value)
+        if event.control.id == "input_record_path":
+            self.post_message(OBSSettingsPane.RecordPathChanged(self, event.value))
+    
+    def watch_record_path(self, value):
+        input: Input = self.query_exactly_one("#input_record_path")
+        input.value = value
diff --git a/src/obs_ctl/interface/element/__init__.py b/src/obs_ctl/interface/element/__init__.py
new file mode 100644 (file)
index 0000000..99d7b11
--- /dev/null
@@ -0,0 +1,2 @@
+from .bool_control import BoolControl
+from .text_readout import TextReadout
\ No newline at end of file
diff --git a/src/obs_ctl/interface/element/bool_control.py b/src/obs_ctl/interface/element/bool_control.py
new file mode 100644 (file)
index 0000000..a6b2d71
--- /dev/null
@@ -0,0 +1,167 @@
+from textual import on
+from textual.app import ComposeResult
+from textual.containers import Container
+from textual.css import query
+from textual.message import Message
+from textual.reactive import reactive
+from textual.widgets import Button, RadioButton
+
+from ...log import getLogger
+
+logger = getLogger(__name__)
+
+class BoolControl(Container):
+    """BoolControl manages a boolean that belongs to something else.
+    
+    In other words, it can display true or false and this can be set
+    on it directly, but its buttons do nothing other than post a
+    message. Designed as i/o for an API"""
+    DEFAULT_CSS = """
+        .bool_control--light {
+            background:$panel;
+            text-align:center;
+            align:center bottom;
+            width:1fr;
+            height:1;
+        }
+        .bool_control--true_button {
+            width:1fr;
+            height:1fr;
+        }
+        .bool_control--false_button {
+            width:1fr;
+            height:1fr;
+        }
+    """
+    COMPONENT_CLASSES = {
+        "bool_control--light",
+        "bool_control--true_button",
+        "bool_control--false_button",
+    }
+    value: reactive[bool] = reactive(False)
+    label: reactive[str] = reactive("Status")
+    true_label: reactive[str] = reactive("Start")
+    false_label: reactive[str] = reactive("Stop")
+    swap_red: reactive[bool] = reactive(False)
+    compact: reactive[bool] = reactive(True)
+    control_layout: reactive[str] = reactive("vertical")
+
+    class MsgBase(Message):
+        control: "BoolControl" = None
+        def __init__(self, control: "BoolControl"):
+            super().__init__()
+            self.control = control
+    class SetTrue(MsgBase): ...
+    class SetFalse(MsgBase): ...
+
+
+    def __init__(
+            self,
+            value: bool,
+            label: str = "Boolean",
+            true_label: str = "Start",
+            false_label: str = "Stop",
+            swap_red: bool = False,
+            compact: bool = True,
+            *children,
+            layout = "vertical",
+            name = None,
+            id = None,
+            classes = None,
+            disabled = False,
+            markup = True):
+        super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
+        self.set_reactive(BoolControl.value, value)
+        self.set_reactive(BoolControl.label, label)
+        self.set_reactive(BoolControl.true_label, true_label)
+        self.set_reactive(BoolControl.false_label, false_label)
+        self.set_reactive(BoolControl.swap_red, swap_red)
+        self.set_reactive(BoolControl.compact, compact)
+        self.set_reactive(BoolControl.control_layout, layout)
+
+    def compose(self) -> ComposeResult:
+        with Container(classes="bool_control--light"):
+            yield RadioButton(
+                label="",
+                value=False,
+                button_first=False,
+                id="light",
+                compact=True,
+                disabled=True,
+                classes="bool_control--light",
+            )
+        yield Button(
+                label="Start",
+                id="true",
+                variant="success",
+                compact=True,
+                classes="bool_control--true_button"
+        )
+        yield Button(
+                label="Stop",
+                id="false",
+                variant="error",
+                compact=True,
+                classes = "bool_control--false_button"
+        )
+
+
+    def _on_mount(self, event):
+        # super()._on_mount(event)
+        self.watch_value(self.value)
+        self.watch_label(self.label)
+        self.watch_true_label(self.true_label)
+        self.watch_false_label(self.false_label)
+        self.watch_swap_red(self.swap_red)
+        self.watch_compact(self.compact)
+        self.watch_control_layout(self.control_layout)
+
+
+    @on(Button.Pressed, "#false")
+    def false_pressed(self, event: Button.Pressed):
+        self.post_message(self.SetFalse(self))
+
+
+    @on(Button.Pressed, "#true")
+    def true_pressed(self):
+        self.post_message(self.SetTrue(self))
+
+
+    def watch_value(self, value: bool) -> None:
+        light: RadioButton = self.query_exactly_one("#light")
+        light.value = value
+
+
+    def watch_label(self, value):
+        light: RadioButton = self.query_exactly_one("#light")
+        light.label = value
+
+
+    def watch_true_label(self, value):
+        true: Button = self.query_exactly_one("#true")
+        true.label = value
+
+
+    def watch_false_label(self, value):
+        false: Button = self.query_exactly_one("#false")
+        false.label = value
+
+
+    def watch_swap_red(self, value):
+        true: Button = self.query_exactly_one("#true")
+        false: Button = self.query_exactly_one("#false")
+        false.variant = "success" if value else "error"
+        true.variant = "error" if value else "success"
+    
+    
+    def watch_compact(self, value):
+        light: RadioButton = self.query_exactly_one("#light")
+        true: Button = self.query_exactly_one("#true")
+        false: Button = self.query_exactly_one("#false")
+        light.compact = value
+        true.compact = value
+        false.compact = value
+    
+
+    def watch_control_layout(self, value):
+        self.set_styles(layout=value)
\ No newline at end of file
diff --git a/src/obs_ctl/interface/element/text_readout.py b/src/obs_ctl/interface/element/text_readout.py
new file mode 100644 (file)
index 0000000..55ede6b
--- /dev/null
@@ -0,0 +1,36 @@
+from textual.containers import Container
+from textual.reactive import reactive
+from textual.widgets import Label
+
+class TextReadout(Container):
+    COMPONENT_CLASSES = {
+        "text_readout--label",
+        "text_readout--text",
+    }
+    text = reactive("Text")
+    label = reactive("Label")
+    readout_layout = reactive("vertical")
+
+    def __init__(self, label, text, *children, layout = "vertical", name = None, id = None, classes = None, disabled = False, markup = True):
+        super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
+        self.set_reactive(TextReadout.label, label)
+        self.set_reactive(TextReadout.text, text)
+        self.set_reactive(TextReadout.readout_layout, layout)
+
+
+    def compose(self):
+        yield Container(Label(self.label, id="label"), classes="text_readout--label")
+        yield Container(Label(self.text, id="text"), classes="text_readout--text")
+    
+    def watch_text(self, value: str):
+        text: Label = self.query_exactly_one("#text")
+        text.update(value)
+    
+
+    def watch_label(self, value):
+        label: Label = self.query_exactly_one("#label")
+        label.update(value)
+
+
+    def watch_readout_layout(self, value):
+        self.set_styles(layout=value)
\ No newline at end of file
diff --git a/src/obs_ctl/interface/message.py b/src/obs_ctl/interface/message.py
new file mode 100644 (file)
index 0000000..650e06b
--- /dev/null
@@ -0,0 +1,8 @@
+from textual.message import Message
+from textual.widget import Widget
+
+class MSGBase(Message):
+    control: Widget = None
+    def __init__(self, control):
+        self.control = control
+        super().__init__()
\ No newline at end of file
diff --git a/src/obs_ctl/interface/molecule/__init__.py b/src/obs_ctl/interface/molecule/__init__.py
new file mode 100644 (file)
index 0000000..ace480d
--- /dev/null
@@ -0,0 +1 @@
+from .record_controls import RecordControls
\ No newline at end of file
diff --git a/src/obs_ctl/interface/molecule/record_controls.py b/src/obs_ctl/interface/molecule/record_controls.py
new file mode 100644 (file)
index 0000000..18e1450
--- /dev/null
@@ -0,0 +1,72 @@
+from textual.containers import ScrollableContainer, Grid
+from textual.message import Message
+from textual.reactive import reactive
+
+from .. import MSGBase
+from ..element import BoolControl
+from ...log import getLogger
+
+logger=getLogger(__name__)
+class RecordControls(ScrollableContainer):
+    DEFAULT_CSS = """
+    Grid {
+        grid-size:2;
+        grid-rows:5;
+        height:10;
+    }
+    """
+
+    recording: reactive[bool] = False
+    paused: reactive[bool] = False
+    streaming: reactive[bool] = False
+
+    class RecordStarted(MSGBase): ...
+    class RecordStopped(MSGBase): ...
+    class RecordPaused(MSGBase): ...
+    class RecordUnpaused(MSGBase): ...
+    class StreamStarted(MSGBase): ...
+    class StreamStopped(MSGBase): ...
+
+    def compose(self):
+        with Grid():
+            yield BoolControl(False, label="Record", id="record_control")
+            yield BoolControl(
+                False,
+                label="Pause",
+                true_label="Pause",
+                false_label="Unpause",
+                swap_red=True,
+                id="pause_control"
+            )
+            yield BoolControl(False, label="Stream", id="stream_control")
+    
+    def on_bool_control_set_true(self, message: BoolControl.SetTrue):
+        match message.control.id:
+            case "record_control":
+                self.post_message(RecordControls.RecordStarted(self))
+            case "pause_control":
+                self.post_message(RecordControls.RecordPaused(self))
+            case "stream_control":
+                self.post_message(RecordControls.StreamStarted(self))
+
+
+    def on_bool_control_set_false(self, message: BoolControl.SetFalse):
+        match message.control.id:
+            case "record_control":
+                self.post_message(RecordControls.RecordStopped(self))
+            case "pause_control":
+                self.post_message(RecordControls.RecordUnpaused(self))
+            case "stream_control":
+                self.post_message(RecordControls.StreamStopped(self))
+    
+    def watch_recording(self, value):
+        control: BoolControl = self.query_exactly_one("#record_control")
+        control.value = value
+    
+    def watch_paused(self, value):
+        control: BoolControl = self.query_exactly_one("#pause_control")
+        control.value = value
+
+    def watch_streaming(self, value):
+        control: BoolControl = self.query_exactly_one("#stream_control")
+        control.value = value
\ No newline at end of file
diff --git a/src/obs_ctl/widget/__init__.py b/src/obs_ctl/widget/__init__.py
deleted file mode 100644 (file)
index 6d1f0e0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-from textual.app import App, ComposeResult
-from textual.containers import Horizontal, VerticalScroll, Grid, Container
-from textual.message import Message
-from textual.reactive import reactive
-from textual.widgets import Label, RadioButton, Button, Input
-from textual.widget import Widget
-from textual.css import query
-
-
-from .. import log
-
-logger = log.getLogger(__name__)
-
-class OBSSettingsPane(VerticalScroll):
-    DEFAULT_CSS = """
-    .obssettingspane--input {
-        width:1fr;
-    }
-    Grid {
-        grid-size:2 1;
-        grid-columns:21 1fr;
-        Label {
-            width:1fr;
-            text-align:right;
-            padding-right:1;
-        }
-    }
-    """
-    COMPONENT_CLASSES = {
-        "obssettingspane--input",
-    }
-    record_path: reactive[str] = reactive("")
-    class RecordPathChanged(Message):
-        control: "OBSSettingsPane" = None
-        record_path: str = None
-        def __init__(self, ctrl, path):
-            super().__init__()
-            self.control = ctrl
-            self.record_path = path
-
-    def compose(self):
-        with Grid():
-            yield Label("Record path:")
-            yield Input("path", id="input_record_path", classes="obssettingspane--input", compact=True)
-    
-    def on_input_submitted(self, event:Input.Submitted):
-        self.set_reactive(OBSSettingsPane.record_path, event.value)
-        if event.control.id == "input_record_path":
-            self.post_message(OBSSettingsPane.RecordPathChanged(self, event.value))
-    
-    def watch_record_path(self, value):
-        input: Input = self.query_exactly_one("#input_record_path")
-        input.value = value
diff --git a/src/obs_ctl/widget/element/bool_control.py b/src/obs_ctl/widget/element/bool_control.py
deleted file mode 100644 (file)
index a6b2d71..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-from textual import on
-from textual.app import ComposeResult
-from textual.containers import Container
-from textual.css import query
-from textual.message import Message
-from textual.reactive import reactive
-from textual.widgets import Button, RadioButton
-
-from ...log import getLogger
-
-logger = getLogger(__name__)
-
-class BoolControl(Container):
-    """BoolControl manages a boolean that belongs to something else.
-    
-    In other words, it can display true or false and this can be set
-    on it directly, but its buttons do nothing other than post a
-    message. Designed as i/o for an API"""
-    DEFAULT_CSS = """
-        .bool_control--light {
-            background:$panel;
-            text-align:center;
-            align:center bottom;
-            width:1fr;
-            height:1;
-        }
-        .bool_control--true_button {
-            width:1fr;
-            height:1fr;
-        }
-        .bool_control--false_button {
-            width:1fr;
-            height:1fr;
-        }
-    """
-    COMPONENT_CLASSES = {
-        "bool_control--light",
-        "bool_control--true_button",
-        "bool_control--false_button",
-    }
-    value: reactive[bool] = reactive(False)
-    label: reactive[str] = reactive("Status")
-    true_label: reactive[str] = reactive("Start")
-    false_label: reactive[str] = reactive("Stop")
-    swap_red: reactive[bool] = reactive(False)
-    compact: reactive[bool] = reactive(True)
-    control_layout: reactive[str] = reactive("vertical")
-
-    class MsgBase(Message):
-        control: "BoolControl" = None
-        def __init__(self, control: "BoolControl"):
-            super().__init__()
-            self.control = control
-    class SetTrue(MsgBase): ...
-    class SetFalse(MsgBase): ...
-
-
-    def __init__(
-            self,
-            value: bool,
-            label: str = "Boolean",
-            true_label: str = "Start",
-            false_label: str = "Stop",
-            swap_red: bool = False,
-            compact: bool = True,
-            *children,
-            layout = "vertical",
-            name = None,
-            id = None,
-            classes = None,
-            disabled = False,
-            markup = True):
-        super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
-        self.set_reactive(BoolControl.value, value)
-        self.set_reactive(BoolControl.label, label)
-        self.set_reactive(BoolControl.true_label, true_label)
-        self.set_reactive(BoolControl.false_label, false_label)
-        self.set_reactive(BoolControl.swap_red, swap_red)
-        self.set_reactive(BoolControl.compact, compact)
-        self.set_reactive(BoolControl.control_layout, layout)
-
-    def compose(self) -> ComposeResult:
-        with Container(classes="bool_control--light"):
-            yield RadioButton(
-                label="",
-                value=False,
-                button_first=False,
-                id="light",
-                compact=True,
-                disabled=True,
-                classes="bool_control--light",
-            )
-        yield Button(
-                label="Start",
-                id="true",
-                variant="success",
-                compact=True,
-                classes="bool_control--true_button"
-        )
-        yield Button(
-                label="Stop",
-                id="false",
-                variant="error",
-                compact=True,
-                classes = "bool_control--false_button"
-        )
-
-
-    def _on_mount(self, event):
-        # super()._on_mount(event)
-        self.watch_value(self.value)
-        self.watch_label(self.label)
-        self.watch_true_label(self.true_label)
-        self.watch_false_label(self.false_label)
-        self.watch_swap_red(self.swap_red)
-        self.watch_compact(self.compact)
-        self.watch_control_layout(self.control_layout)
-
-
-    @on(Button.Pressed, "#false")
-    def false_pressed(self, event: Button.Pressed):
-        self.post_message(self.SetFalse(self))
-
-
-    @on(Button.Pressed, "#true")
-    def true_pressed(self):
-        self.post_message(self.SetTrue(self))
-
-
-    def watch_value(self, value: bool) -> None:
-        light: RadioButton = self.query_exactly_one("#light")
-        light.value = value
-
-
-    def watch_label(self, value):
-        light: RadioButton = self.query_exactly_one("#light")
-        light.label = value
-
-
-    def watch_true_label(self, value):
-        true: Button = self.query_exactly_one("#true")
-        true.label = value
-
-
-    def watch_false_label(self, value):
-        false: Button = self.query_exactly_one("#false")
-        false.label = value
-
-
-    def watch_swap_red(self, value):
-        true: Button = self.query_exactly_one("#true")
-        false: Button = self.query_exactly_one("#false")
-        false.variant = "success" if value else "error"
-        true.variant = "error" if value else "success"
-    
-    
-    def watch_compact(self, value):
-        light: RadioButton = self.query_exactly_one("#light")
-        true: Button = self.query_exactly_one("#true")
-        false: Button = self.query_exactly_one("#false")
-        light.compact = value
-        true.compact = value
-        false.compact = value
-    
-
-    def watch_control_layout(self, value):
-        self.set_styles(layout=value)
\ No newline at end of file
diff --git a/src/obs_ctl/widget/element/text_readout.py b/src/obs_ctl/widget/element/text_readout.py
deleted file mode 100644 (file)
index 55ede6b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-from textual.containers import Container
-from textual.reactive import reactive
-from textual.widgets import Label
-
-class TextReadout(Container):
-    COMPONENT_CLASSES = {
-        "text_readout--label",
-        "text_readout--text",
-    }
-    text = reactive("Text")
-    label = reactive("Label")
-    readout_layout = reactive("vertical")
-
-    def __init__(self, label, text, *children, layout = "vertical", name = None, id = None, classes = None, disabled = False, markup = True):
-        super().__init__(*children, name=name, id=id, classes=classes, disabled=disabled, markup=markup)
-        self.set_reactive(TextReadout.label, label)
-        self.set_reactive(TextReadout.text, text)
-        self.set_reactive(TextReadout.readout_layout, layout)
-
-
-    def compose(self):
-        yield Container(Label(self.label, id="label"), classes="text_readout--label")
-        yield Container(Label(self.text, id="text"), classes="text_readout--text")
-    
-    def watch_text(self, value: str):
-        text: Label = self.query_exactly_one("#text")
-        text.update(value)
-    
-
-    def watch_label(self, value):
-        label: Label = self.query_exactly_one("#label")
-        label.update(value)
-
-
-    def watch_readout_layout(self, value):
-        self.set_styles(layout=value)
\ No newline at end of file