mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
impl all froms (8263loc)
This commit is contained in:
parent
f921260f6f
commit
48f83fa94d
13 changed files with 110 additions and 143 deletions
|
|
@ -50,41 +50,35 @@ impl ItemColor {
|
||||||
self.okhsl.mix(other.okhsl, distance).into()
|
self.okhsl.mix(other.okhsl, distance).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<Color> for ItemPalette {
|
from!(|base: Color|ItemPalette = Self::from(ItemColor::from(base)));
|
||||||
fn from (base: Color) -> Self {
|
from!(|base: ItemColor|ItemPalette = {
|
||||||
Self::from(ItemColor::from(base))
|
let mut light = base.okhsl.clone();
|
||||||
}
|
light.lightness = (light.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
||||||
}
|
let mut lighter = light.clone();
|
||||||
impl From<ItemColor> for ItemPalette {
|
lighter.lightness = (lighter.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
||||||
fn from (base: ItemColor) -> Self {
|
let mut lightest = lighter.clone();
|
||||||
let mut light = base.okhsl.clone();
|
lightest.lightness = (lightest.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
||||||
light.lightness = (light.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
|
||||||
let mut lighter = light.clone();
|
|
||||||
lighter.lightness = (lighter.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
|
||||||
let mut lightest = lighter.clone();
|
|
||||||
lightest.lightness = (lightest.lightness * 1.3).min(Okhsl::<f32>::max_lightness());
|
|
||||||
|
|
||||||
let mut dark = base.okhsl.clone();
|
let mut dark = base.okhsl.clone();
|
||||||
dark.lightness = (dark.lightness * 0.75).max(Okhsl::<f32>::min_lightness());
|
dark.lightness = (dark.lightness * 0.75).max(Okhsl::<f32>::min_lightness());
|
||||||
dark.saturation = (dark.saturation * 0.75).max(Okhsl::<f32>::min_saturation());
|
dark.saturation = (dark.saturation * 0.75).max(Okhsl::<f32>::min_saturation());
|
||||||
let mut darker = dark.clone();
|
let mut darker = dark.clone();
|
||||||
darker.lightness = (darker.lightness * 0.66).max(Okhsl::<f32>::min_lightness());
|
darker.lightness = (darker.lightness * 0.66).max(Okhsl::<f32>::min_lightness());
|
||||||
darker.saturation = (darker.saturation * 0.66).max(Okhsl::<f32>::min_saturation());
|
darker.saturation = (darker.saturation * 0.66).max(Okhsl::<f32>::min_saturation());
|
||||||
let mut darkest = darker.clone();
|
let mut darkest = darker.clone();
|
||||||
darkest.lightness = (darkest.lightness * 0.50).max(Okhsl::<f32>::min_lightness());
|
darkest.lightness = (darkest.lightness * 0.50).max(Okhsl::<f32>::min_lightness());
|
||||||
darkest.saturation = (darkest.saturation * 0.50).max(Okhsl::<f32>::min_saturation());
|
darkest.saturation = (darkest.saturation * 0.50).max(Okhsl::<f32>::min_saturation());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
base,
|
base,
|
||||||
light: light.into(),
|
light: light.into(),
|
||||||
lighter: lighter.into(),
|
lighter: lighter.into(),
|
||||||
lightest: lightest.into(),
|
lightest: lightest.into(),
|
||||||
dark: dark.into(),
|
dark: dark.into(),
|
||||||
darker: darker.into(),
|
darker: darker.into(),
|
||||||
darkest: darkest.into(),
|
darkest: darkest.into(),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
impl ItemPalette {
|
impl ItemPalette {
|
||||||
pub fn random () -> Self {
|
pub fn random () -> Self {
|
||||||
ItemColor::random().into()
|
ItemColor::random().into()
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,31 @@
|
||||||
|
pub use ::jack as libjack;
|
||||||
pub(crate) mod activate;
|
pub(crate) mod activate; pub(crate) use self::activate::*;
|
||||||
pub(crate) mod audio; pub(crate) use self::audio::*;
|
pub(crate) mod audio; pub(crate) use self::audio::*;
|
||||||
pub(crate) mod client; pub(crate) use self::client::*;
|
pub(crate) mod client; pub(crate) use self::client::*;
|
||||||
pub(crate) mod from_jack;
|
|
||||||
pub(crate) mod jack_event; pub(crate) use self::jack_event::*;
|
pub(crate) mod jack_event; pub(crate) use self::jack_event::*;
|
||||||
pub(crate) mod ports; pub(crate) use self::ports::*;
|
pub(crate) mod ports; pub(crate) use self::ports::*;
|
||||||
|
pub(crate) use ::jack::{
|
||||||
|
contrib::ClosureProcessHandler,
|
||||||
|
Client, AsyncClient, ClientOptions, ClientStatus,
|
||||||
|
ProcessScope, Control, CycleTimes,
|
||||||
|
Port, PortId,
|
||||||
|
PortSpec, MidiIn, MidiOut, AudioIn, AudioOut, Unowned,
|
||||||
|
Transport, TransportState, MidiIter, RawMidi,
|
||||||
|
Frames,
|
||||||
|
NotificationHandler,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Implement [TryFrom<&Arc<RwLock<JackClient>>>]: create app state from wrapped JACK handle.
|
||||||
|
#[macro_export] macro_rules! from_jack {
|
||||||
|
(|$jack:ident|$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)? $cb:expr) => {
|
||||||
|
impl $(<$($L),*$($T $(: $U)?),*>)? TryFrom<&Arc<RwLock<JackClient>>> for $Struct $(<$($L),*$($T),*>)? {
|
||||||
|
type Error = Box<dyn std::error::Error>;
|
||||||
|
fn try_from ($jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||||
|
Ok($cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
pub type DynamicAsyncClient = AsyncClient<DynamicNotifications, DynamicAudioHandler>;
|
||||||
|
pub type DynamicAudioHandler = ClosureProcessHandler<(), BoxedAudioHandler>;
|
||||||
|
pub type BoxedAudioHandler = Box<dyn FnMut(&Client, &ProcessScope) -> Control + Send>;
|
||||||
/// Wraps [Client] or [DynamicAsyncClient] in place.
|
/// Wraps [Client] or [DynamicAsyncClient] in place.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum JackClient {
|
pub enum JackClient {
|
||||||
|
|
@ -10,7 +12,17 @@ pub enum JackClient {
|
||||||
/// After activation. Must not be dropped for JACK thread to persist.
|
/// After activation. Must not be dropped for JACK thread to persist.
|
||||||
Active(DynamicAsyncClient),
|
Active(DynamicAsyncClient),
|
||||||
}
|
}
|
||||||
|
from!(|jack: JackClient|Client = match jack {
|
||||||
|
JackClient::Inactive(client) => client,
|
||||||
|
JackClient::Activating => panic!("jack client still activating"),
|
||||||
|
JackClient::Active(_) => panic!("jack client already activated"),
|
||||||
|
});
|
||||||
|
impl JackClient {
|
||||||
|
pub fn new (name: &str) -> Usually<Self> {
|
||||||
|
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||||
|
Ok(Self::Inactive(client))
|
||||||
|
}
|
||||||
|
}
|
||||||
impl AudioEngine for JackClient {
|
impl AudioEngine for JackClient {
|
||||||
fn client(&self) -> &Client {
|
fn client(&self) -> &Client {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -36,26 +48,3 @@ impl AudioEngine for JackClient {
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DynamicAsyncClient = AsyncClient<DynamicNotifications, DynamicAudioHandler>;
|
|
||||||
|
|
||||||
pub type DynamicAudioHandler = ClosureProcessHandler<(), BoxedAudioHandler>;
|
|
||||||
|
|
||||||
pub type BoxedAudioHandler = Box<dyn FnMut(&Client, &ProcessScope) -> Control + Send>;
|
|
||||||
|
|
||||||
impl JackClient {
|
|
||||||
pub fn new (name: &str) -> Usually<Self> {
|
|
||||||
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
|
||||||
Ok(Self::Inactive(client))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JackClient> for Client {
|
|
||||||
fn from (jack: JackClient) -> Client {
|
|
||||||
match jack {
|
|
||||||
JackClient::Inactive(client) => client,
|
|
||||||
JackClient::Activating => panic!("jack client still activating"),
|
|
||||||
JackClient::Active(_) => panic!("jack client already activated"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
/// Implement [TryFrom<&Arc<RwLock<JackClient>>>]: create app state from wrapped JACK handle.
|
|
||||||
#[macro_export] macro_rules! from_jack {
|
|
||||||
(|$jack:ident|$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)? $cb:expr) => {
|
|
||||||
impl $(<$($L),*$($T $(: $U)?),*>)? TryFrom<&Arc<RwLock<JackClient>>> for $Struct $(<$($L),*$($T),*>)? {
|
|
||||||
type Error = Box<dyn std::error::Error>;
|
|
||||||
fn try_from ($jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
|
||||||
Ok($cb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -65,18 +65,6 @@ pub(crate) use ratatui::{
|
||||||
backend::{Backend, CrosstermBackend, ClearType}
|
backend::{Backend, CrosstermBackend, ClearType}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use ::jack as libjack;
|
|
||||||
pub(crate) use ::jack::{
|
|
||||||
contrib::ClosureProcessHandler,
|
|
||||||
Client, AsyncClient, ClientOptions, ClientStatus,
|
|
||||||
ProcessScope, Control, CycleTimes,
|
|
||||||
Port, PortId,
|
|
||||||
PortSpec, MidiIn, MidiOut, AudioOut, Unowned,
|
|
||||||
Transport, TransportState, MidiIter, RawMidi,
|
|
||||||
Frames,
|
|
||||||
NotificationHandler,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use ::midly;
|
pub use ::midly;
|
||||||
pub(crate) use ::midly::{
|
pub(crate) use ::midly::{
|
||||||
Smf,
|
Smf,
|
||||||
|
|
|
||||||
|
|
@ -63,25 +63,23 @@ pub struct ClockModel {
|
||||||
pub chunk: Arc<AtomicUsize>,
|
pub chunk: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Arc<RwLock<JackClient>>> for ClockModel {
|
from!(|jack: &Arc<RwLock<JackClient>>| ClockModel = {
|
||||||
fn from (jack: &Arc<RwLock<JackClient>>) -> Self {
|
let jack = jack.read().unwrap();
|
||||||
let jack = jack.read().unwrap();
|
let chunk = jack.client().buffer_size();
|
||||||
let chunk = jack.client().buffer_size();
|
let transport = jack.client().transport();
|
||||||
let transport = jack.client().transport();
|
let timebase = Arc::new(Timebase::default());
|
||||||
let timebase = Arc::new(Timebase::default());
|
Self {
|
||||||
Self {
|
quant: Arc::new(24.into()),
|
||||||
quant: Arc::new(24.into()),
|
sync: Arc::new(384.into()),
|
||||||
sync: Arc::new(384.into()),
|
transport: Arc::new(transport),
|
||||||
transport: Arc::new(transport),
|
chunk: Arc::new((chunk as usize).into()),
|
||||||
chunk: Arc::new((chunk as usize).into()),
|
global: Arc::new(Moment::zero(&timebase)),
|
||||||
global: Arc::new(Moment::zero(&timebase)),
|
playhead: Arc::new(Moment::zero(&timebase)),
|
||||||
playhead: Arc::new(Moment::zero(&timebase)),
|
offset: Arc::new(Moment::zero(&timebase)),
|
||||||
offset: Arc::new(Moment::zero(&timebase)),
|
started: RwLock::new(None).into(),
|
||||||
started: RwLock::new(None).into(),
|
timebase,
|
||||||
timebase,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
impl std::fmt::Debug for ClockModel {
|
impl std::fmt::Debug for ClockModel {
|
||||||
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ pub(crate) use tui_border::*;
|
||||||
mod app_transport; pub(crate) use app_transport::*;
|
mod app_transport; pub(crate) use app_transport::*;
|
||||||
mod app_sequencer; pub(crate) use app_sequencer::*;
|
mod app_sequencer; pub(crate) use app_sequencer::*;
|
||||||
mod app_sampler; pub(crate) use app_sampler::*;
|
mod app_sampler; pub(crate) use app_sampler::*;
|
||||||
mod app_groovebox;
|
mod app_groovebox; pub(crate) use app_groovebox::*;
|
||||||
mod app_arranger; pub(crate) use app_arranger::*;
|
mod app_arranger; pub(crate) use app_arranger::*;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@ from_jack!(|jack| ArrangerTui {
|
||||||
)));
|
)));
|
||||||
Self {
|
Self {
|
||||||
clock,
|
clock,
|
||||||
phrases: PhraseListModel::from(&phrase),
|
phrases: (&phrase).into(),
|
||||||
editor: PhraseEditorModel::from(&phrase),
|
editor: (&phrase).into(),
|
||||||
selected: ArrangerSelection::Clip(0, 0),
|
selected: ArrangerSelection::Clip(0, 0),
|
||||||
scenes: vec![],
|
scenes: vec![],
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
|
|
@ -282,13 +282,13 @@ fn any_size <E: Engine> (_: E::Size) -> Perhaps<E::Size>{
|
||||||
Ok(Some([0.into(),0.into()].into()))
|
Ok(Some([0.into(),0.into()].into()))
|
||||||
}
|
}
|
||||||
impl ArrangerTui {
|
impl ArrangerTui {
|
||||||
fn selected (&self) -> ArrangerSelection {
|
pub fn selected (&self) -> ArrangerSelection {
|
||||||
self.selected
|
self.selected
|
||||||
}
|
}
|
||||||
fn selected_mut (&mut self) -> &mut ArrangerSelection {
|
pub fn selected_mut (&mut self) -> &mut ArrangerSelection {
|
||||||
&mut self.selected
|
&mut self.selected
|
||||||
}
|
}
|
||||||
fn activate (&mut self) -> Usually<()> {
|
pub fn activate (&mut self) -> Usually<()> {
|
||||||
if let ArrangerSelection::Scene(s) = self.selected {
|
if let ArrangerSelection::Scene(s) = self.selected {
|
||||||
for (t, track) in self.tracks.iter_mut().enumerate() {
|
for (t, track) in self.tracks.iter_mut().enumerate() {
|
||||||
let phrase = self.scenes[s].clips[t].clone();
|
let phrase = self.scenes[s].clips[t].clone();
|
||||||
|
|
@ -305,15 +305,15 @@ impl ArrangerTui {
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn selected_phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
|
pub fn selected_phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
|
||||||
self.selected_scene()?.clips.get(self.selected.track()?)?.clone()
|
self.selected_scene()?.clips.get(self.selected.track()?)?.clone()
|
||||||
}
|
}
|
||||||
fn toggle_loop (&mut self) {
|
pub fn toggle_loop (&mut self) {
|
||||||
if let Some(phrase) = self.selected_phrase() {
|
if let Some(phrase) = self.selected_phrase() {
|
||||||
phrase.write().unwrap().toggle_loop()
|
phrase.write().unwrap().toggle_loop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn randomize_color (&mut self) {
|
pub fn randomize_color (&mut self) {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangerSelection::Mix => {
|
ArrangerSelection::Mix => {
|
||||||
self.color = ItemPalette::random()
|
self.color = ItemPalette::random()
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ pub struct TransportTui {
|
||||||
pub clock: ClockModel,
|
pub clock: ClockModel,
|
||||||
pub size: Measure<Tui>,
|
pub size: Measure<Tui>,
|
||||||
pub cursor: (usize, usize),
|
pub cursor: (usize, usize),
|
||||||
pub focus: FocusState<TransportFocus>,
|
pub focus: TransportFocus,
|
||||||
}
|
}
|
||||||
from_jack!(|jack|TransportTui Self {
|
from_jack!(|jack|TransportTui Self {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
clock: ClockModel::from(jack),
|
clock: ClockModel::from(jack),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
cursor: (0, 0),
|
cursor: (0, 0),
|
||||||
focus: FocusState::Entered(TransportFocus::PlayPause)
|
focus: TransportFocus::PlayPause
|
||||||
});
|
});
|
||||||
has_clock!(|self:TransportTui|&self.clock);
|
has_clock!(|self:TransportTui|&self.clock);
|
||||||
audio!(|self:TransportTui,client,scope|ClockAudio(self).process(client, scope));
|
audio!(|self:TransportTui,client,scope|ClockAudio(self).process(client, scope));
|
||||||
|
|
@ -131,10 +131,10 @@ render!(<Tui>|self: PlayPause|Tui::bg(
|
||||||
impl HasFocus for TransportTui {
|
impl HasFocus for TransportTui {
|
||||||
type Item = TransportFocus;
|
type Item = TransportFocus;
|
||||||
fn focused (&self) -> Self::Item {
|
fn focused (&self) -> Self::Item {
|
||||||
self.focus.inner()
|
self.focus
|
||||||
}
|
}
|
||||||
fn set_focused (&mut self, to: Self::Item) {
|
fn set_focused (&mut self, to: Self::Item) {
|
||||||
self.focus.set_inner(to)
|
self.focus = to
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,8 +147,6 @@ pub enum TransportFocus {
|
||||||
Clock,
|
Clock,
|
||||||
Quant,
|
Quant,
|
||||||
}
|
}
|
||||||
from!(|state: &TransportTui|Option<TransportTui> = Some(state.focus.inner()));
|
|
||||||
|
|
||||||
impl FocusWrap<TransportFocus> for TransportFocus {
|
impl FocusWrap<TransportFocus> for TransportFocus {
|
||||||
fn wrap <'a, W: Render<Tui>> (self, focus: TransportFocus, content: &'a W)
|
fn wrap <'a, W: Render<Tui>> (self, focus: TransportFocus, content: &'a W)
|
||||||
-> impl Render<Tui> + 'a
|
-> impl Render<Tui> + 'a
|
||||||
|
|
@ -177,7 +175,7 @@ pub trait TransportControl<T>: HasClock + {
|
||||||
|
|
||||||
impl TransportControl<TransportFocus> for TransportTui {
|
impl TransportControl<TransportFocus> for TransportTui {
|
||||||
fn transport_focused (&self) -> Option<TransportFocus> {
|
fn transport_focused (&self) -> Option<TransportFocus> {
|
||||||
Some(self.focus.inner())
|
Some(self.focus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,11 +48,11 @@ pub struct ArrangerVCursor {
|
||||||
header_h: u16,
|
header_h: u16,
|
||||||
}
|
}
|
||||||
from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
|
from!(|args:(&ArrangerTui, usize)|ArrangerVCursor = Self {
|
||||||
cols: track_widths(state.tracks()),
|
cols: track_widths(args.0.tracks()),
|
||||||
rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
|
rows: ArrangerScene::ppqs(args.0.scenes(), args.1),
|
||||||
focused: true,
|
focused: true,
|
||||||
selected: state.selected,
|
selected: args.0.selected(),
|
||||||
scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16,
|
scenes_w: 3 + ArrangerScene::longest_name(args.0.scenes()) as u16,
|
||||||
header_h: 3,
|
header_h: 3,
|
||||||
});
|
});
|
||||||
render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{
|
render!(<Tui>|self: ArrangerVCursor|render(move|to: &mut TuiOutput|{
|
||||||
|
|
|
||||||
|
|
@ -207,22 +207,18 @@ impl PhraseEditorModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Arc<RwLock<Phrase>>> for PhraseEditorModel {
|
from!(|phrase: &Arc<RwLock<Phrase>>|PhraseEditorModel = {
|
||||||
fn from (phrase: &Arc<RwLock<Phrase>>) -> Self {
|
let mut model = Self::from(Some(phrase.clone()));
|
||||||
let mut model = Self::from(Some(phrase.clone()));
|
model.redraw();
|
||||||
model.redraw();
|
model
|
||||||
model
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Option<Arc<RwLock<Phrase>>>> for PhraseEditorModel {
|
from!(|phrase: Option<Arc<RwLock<Phrase>>>|PhraseEditorModel = {
|
||||||
fn from (phrase: Option<Arc<RwLock<Phrase>>>) -> Self {
|
let mut model = Self::default();
|
||||||
let mut model = Self::default();
|
*model.phrase_mut() = phrase;
|
||||||
*model.phrase_mut() = phrase;
|
model.redraw();
|
||||||
model.redraw();
|
model
|
||||||
model
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Debug for PhraseEditorModel {
|
impl std::fmt::Debug for PhraseEditorModel {
|
||||||
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ impl Default for PhraseListModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
from!(|phrase:<&Arc<RwLock<Phrase>>>| PhraseListModel = {
|
from!(|phrase:&Arc<RwLock<Phrase>>|PhraseListModel = {
|
||||||
let mut model = Self::default();
|
let mut model = Self::default();
|
||||||
model.phrases.push(phrase.clone());
|
model.phrases.push(phrase.clone());
|
||||||
model.phrase.store(1, Relaxed);
|
model.phrase.store(1, Relaxed);
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,7 @@ impl BigBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(usize, usize)> for BigBuffer { // cuteness overload
|
from!(|size:(usize, usize)| BigBuffer = Self::new(size.0, size.1));
|
||||||
fn from ((width, height): (usize, usize)) -> Self {
|
|
||||||
Self::new(width, height)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn buffer_update (buf: &mut Buffer, area: [u16;4], callback: &impl Fn(&mut Cell, u16, u16)) {
|
pub fn buffer_update (buf: &mut Buffer, area: [u16;4], callback: &impl Fn(&mut Cell, u16, u16)) {
|
||||||
for row in 0..area.h() {
|
for row in 0..area.h() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue