starting work on UI
This commit is contained in:
7
src/main.py
Normal file
7
src/main.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from ui.app import AppUI
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# start the ui
|
||||||
|
app = AppUI()
|
||||||
|
app.run()
|
||||||
12
src/ui/app.py
Normal file
12
src/ui/app.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.widgets import Footer
|
||||||
|
|
||||||
|
from ui.widgets.sidebar import Sidebar
|
||||||
|
from ui.widgets.timeline import Timeline
|
||||||
|
|
||||||
|
|
||||||
|
class AppUI(App):
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Sidebar()
|
||||||
|
yield Timeline()
|
||||||
|
yield Footer()
|
||||||
68
src/ui/widgets/channel.py
Normal file
68
src/ui/widgets/channel.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
from textual.containers import VerticalGroup, Horizontal
|
||||||
|
from textual.app import ComposeResult
|
||||||
|
from textual.widgets import Checkbox, Input, Static
|
||||||
|
|
||||||
|
from textual_slider import Slider
|
||||||
|
|
||||||
|
|
||||||
|
class Channel(VerticalGroup):
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
Channel {
|
||||||
|
height: 8;
|
||||||
|
border: tall $surface-lighten-1;
|
||||||
|
background: $surface-darken-1;
|
||||||
|
padding: 0 1;
|
||||||
|
margin-bottom: 1;
|
||||||
|
|
||||||
|
#name {
|
||||||
|
padding: 0 1;
|
||||||
|
margin-bottom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkbox {
|
||||||
|
margin-right: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-slider {
|
||||||
|
height: 1;
|
||||||
|
Static {
|
||||||
|
width: 50%;
|
||||||
|
margin-right: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
width: 45%;
|
||||||
|
border: none;
|
||||||
|
max-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#channel-buttons {
|
||||||
|
margin-top: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, channel_name: str = "", muted: bool = False, solo: bool = False, pan: float = 0, volume: float = 0):
|
||||||
|
super().__init__()
|
||||||
|
self.channel_name = channel_name
|
||||||
|
self.muted = muted
|
||||||
|
self.solo = solo
|
||||||
|
self.pan = pan
|
||||||
|
self.volume = volume
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Input(placeholder="Channel Name", compact=True, id="name", value=self.channel_name)
|
||||||
|
|
||||||
|
with Horizontal(classes="channel-slider"):
|
||||||
|
yield Static("Pan (center):")
|
||||||
|
yield Slider(-100, 100, step=1, value=self.pan)
|
||||||
|
with Horizontal(classes="channel-slider"):
|
||||||
|
yield Static("Volume (+ 0Db):")
|
||||||
|
yield Slider(-15, 15, step=0.1, value=self.volume)
|
||||||
|
|
||||||
|
with Horizontal(id="channel-buttons"):
|
||||||
|
yield Checkbox("Mute", compact=True, id="mute", tooltip="Mute this track", value=self.muted)
|
||||||
|
yield Checkbox("Solo", compact=True, id="solo", tooltip="Hear only this track", value=self.solo)
|
||||||
|
|
||||||
28
src/ui/widgets/sidebar.py
Normal file
28
src/ui/widgets/sidebar.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from textual.containers import Vertical, VerticalScroll, Horizontal
|
||||||
|
from textual.widgets import Button, ListView
|
||||||
|
from textual.app import ComposeResult
|
||||||
|
|
||||||
|
from ui.widgets.channel import Channel
|
||||||
|
|
||||||
|
|
||||||
|
class Sidebar(Vertical):
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
Sidebar {
|
||||||
|
dock: left;
|
||||||
|
background: $surface;
|
||||||
|
width: 40;
|
||||||
|
border-right: tall $surface-lighten-1;
|
||||||
|
padding: 1;
|
||||||
|
|
||||||
|
#add-channel {
|
||||||
|
min-width: 100%;
|
||||||
|
margin: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
with VerticalScroll(id="channels"):
|
||||||
|
yield Channel()
|
||||||
|
yield Channel()
|
||||||
|
yield Button("+ New Channel", variant="success", id="add-channel")
|
||||||
27
src/ui/widgets/timeline.py
Normal file
27
src/ui/widgets/timeline.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
from textual.containers import VerticalScroll, Horizontal
|
||||||
|
from textual.app import ComposeResult
|
||||||
|
|
||||||
|
|
||||||
|
class TimelineRow(Horizontal):
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
TimelineRow {
|
||||||
|
background: $surface-lighten-1;
|
||||||
|
height: 8;
|
||||||
|
margin-bottom: 1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield from ()
|
||||||
|
|
||||||
|
class Timeline(VerticalScroll):
|
||||||
|
DEFAULT_CSS = """
|
||||||
|
Timeline {
|
||||||
|
padding: 1 0;
|
||||||
|
hatch: "-" $surface-lighten-1;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield TimelineRow()
|
||||||
|
yield TimelineRow()
|
||||||
Reference in New Issue
Block a user