mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
migrate Color -> ItemColor and remove unused
This commit is contained in:
parent
33600e890f
commit
eb1e3179a4
6 changed files with 59 additions and 76 deletions
|
|
@ -2,33 +2,37 @@ use crate::*;
|
||||||
use rand::{thread_rng, distributions::uniform::UniformSampler};
|
use rand::{thread_rng, distributions::uniform::UniformSampler};
|
||||||
pub use palette::{*, convert::*, okhsl::*};
|
pub use palette::{*, convert::*, okhsl::*};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
/// A color in OKHSL and RGB representations.
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct ItemColor {
|
pub struct ItemColor {
|
||||||
pub okhsl: Okhsl<f32>,
|
pub okhsl: Okhsl<f32>,
|
||||||
pub rgb: Color,
|
pub rgb: Color,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Copy, Clone)]
|
/// A color in OKHSL and RGB with lighter and darker variants.
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct ItemColorTriplet {
|
pub struct ItemColorTriplet {
|
||||||
pub base: ItemColor,
|
pub base: ItemColor,
|
||||||
pub light: ItemColor,
|
pub light: ItemColor,
|
||||||
pub dark: ItemColor,
|
pub dark: ItemColor,
|
||||||
}
|
}
|
||||||
|
/// Adds TUI RGB representation to an OKHSL value.
|
||||||
impl From<Okhsl<f32>> for ItemColor {
|
impl From<Okhsl<f32>> for ItemColor {
|
||||||
fn from (okhsl: Okhsl<f32>) -> Self {
|
fn from (okhsl: Okhsl<f32>) -> Self { Self { okhsl, rgb: okhsl_to_rgb(okhsl) } }
|
||||||
Self { okhsl, rgb: okhsl_to_rgb(okhsl) }
|
}
|
||||||
}
|
/// Adds OKHSL representation to a TUI RGB value.
|
||||||
|
impl From<Color> for ItemColor {
|
||||||
|
fn from (rgb: Color) -> Self { Self { rgb, okhsl: rgb_to_okhsl(rgb) } }
|
||||||
}
|
}
|
||||||
impl ItemColor {
|
impl ItemColor {
|
||||||
pub fn random () -> Self {
|
pub fn random () -> Self { random_okhsl().into() }
|
||||||
random_okhsl().into()
|
|
||||||
}
|
|
||||||
pub fn random_dark () -> Self {
|
pub fn random_dark () -> Self {
|
||||||
random_okhsl_dark().into()
|
let mut rng = thread_rng();
|
||||||
|
let lo = Okhsl::new(-180.0, 0.01, 0.05);
|
||||||
|
let hi = Okhsl::new( 180.0, 0.5, 0.2);
|
||||||
|
UniformOkhsl::new(lo, hi).sample(&mut rng).into()
|
||||||
}
|
}
|
||||||
pub fn random_near (other: Self, distance: f32) -> Self {
|
pub fn random_near (other: Self, distance: f32) -> Self {
|
||||||
if distance > 1.0 {
|
if distance > 1.0 { panic!("ItemColor::random_near takes distance between 0.0 and 1.0"); }
|
||||||
panic!("random_color_near requires distance between 0.0 and 1.0");
|
|
||||||
}
|
|
||||||
other.okhsl.mix(random_okhsl(), distance).into()
|
other.okhsl.mix(random_okhsl(), distance).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,18 +50,9 @@ impl From<ItemColor> for ItemColorTriplet {
|
||||||
|
|
||||||
pub fn random_okhsl () -> Okhsl<f32> {
|
pub fn random_okhsl () -> Okhsl<f32> {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
UniformOkhsl::new(
|
let lo = Okhsl::new(-180.0, 0.01, 0.2);
|
||||||
Okhsl::new(-180.0, 0.01, 0.2),
|
let hi = Okhsl::new( 180.0, 0.9, 0.5);
|
||||||
Okhsl::new( 180.0, 0.9, 0.5),
|
UniformOkhsl::new(lo, hi).sample(&mut rng)
|
||||||
).sample(&mut rng)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn random_okhsl_dark () -> Okhsl<f32> {
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
UniformOkhsl::new(
|
|
||||||
Okhsl::new(-180.0, 0.01, 0.05),
|
|
||||||
Okhsl::new( 180.0, 0.5, 0.2),
|
|
||||||
).sample(&mut rng)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn okhsl_to_rgb (color: Okhsl<f32>) -> Color {
|
pub fn okhsl_to_rgb (color: Okhsl<f32>) -> Color {
|
||||||
|
|
@ -65,26 +60,14 @@ pub fn okhsl_to_rgb (color: Okhsl<f32>) -> Color {
|
||||||
Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,)
|
Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn random_color () -> Color {
|
pub fn rgb_to_okhsl (color: Color) -> Okhsl<f32> {
|
||||||
okhsl_to_rgb(random_okhsl())
|
if let Color::Rgb(r, g, b) = color {
|
||||||
}
|
Okhsl::from_color(Srgb::new(
|
||||||
|
r as f32 / 255.0,
|
||||||
pub fn random_color_dark () -> Color {
|
g as f32 / 255.0,
|
||||||
okhsl_to_rgb(random_okhsl_dark())
|
b as f32 / 255.0,
|
||||||
}
|
))
|
||||||
|
|
||||||
pub fn random_color_near (color: Color, distance: f32) -> Color {
|
|
||||||
let (r, g, b) = if let Color::Rgb(r, g, b) = color {
|
|
||||||
(r, g, b)
|
|
||||||
} else {
|
} else {
|
||||||
panic!("random_color_near works only with Color::Rgb")
|
unreachable!("only Color::Rgb is supported")
|
||||||
};
|
|
||||||
if distance > 1.0 {
|
|
||||||
panic!("random_color_near requires distance between 0.0 and 1.0");
|
|
||||||
}
|
}
|
||||||
okhsl_to_rgb(Okhsl::from_color(Srgb::new(
|
|
||||||
r as f32 / 255.0,
|
|
||||||
g as f32 / 255.0,
|
|
||||||
b as f32 / 255.0,
|
|
||||||
)).mix(random_okhsl(), distance))
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ pub struct Arrangement<E: Engine> {
|
||||||
/// Whether the arranger is currently focused
|
/// Whether the arranger is currently focused
|
||||||
pub focused: bool,
|
pub focused: bool,
|
||||||
/// Background color of arrangement
|
/// Background color of arrangement
|
||||||
pub color: Color,
|
pub color: ItemColor,
|
||||||
/// Width and height of arrangement area at last render
|
/// Width and height of arrangement area at last render
|
||||||
pub size: Measure<E>,
|
pub size: Measure<E>,
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +78,7 @@ pub struct ArrangementTrack {
|
||||||
/// Preferred width of track column
|
/// Preferred width of track column
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
/// Identifying color of track
|
/// Identifying color of track
|
||||||
pub color: Color,
|
pub color: ItemColor,
|
||||||
/// MIDI player/recorder
|
/// MIDI player/recorder
|
||||||
pub player: PhrasePlayer,
|
pub player: PhrasePlayer,
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ pub struct Scene {
|
||||||
/// Clips in scene, one per track
|
/// Clips in scene, one per track
|
||||||
pub clips: Vec<Option<Arc<RwLock<Phrase>>>>,
|
pub clips: Vec<Option<Arc<RwLock<Phrase>>>>,
|
||||||
/// Identifying color of scene
|
/// Identifying color of scene
|
||||||
pub color: Color,
|
pub color: ItemColor,
|
||||||
}
|
}
|
||||||
#[derive(PartialEq, Clone, Copy)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
/// Represents the current user selection in the arranger
|
/// Represents the current user selection in the arranger
|
||||||
|
|
@ -232,7 +232,7 @@ impl<E: Engine> Arrangement<E> {
|
||||||
scenes: vec![],
|
scenes: vec![],
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
focused: false,
|
focused: false,
|
||||||
color: Color::Rgb(28, 35, 25),
|
color: Color::Rgb(28, 35, 25).into(),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -374,11 +374,11 @@ impl<E: Engine> Arrangement<E> {
|
||||||
}
|
}
|
||||||
pub fn randomize_color (&mut self) {
|
pub fn randomize_color (&mut self) {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangementFocus::Mix => { self.color = random_color_dark() },
|
ArrangementFocus::Mix => { self.color = ItemColor::random_dark() },
|
||||||
ArrangementFocus::Track(t) => { self.tracks[t].color = random_color() },
|
ArrangementFocus::Track(t) => { self.tracks[t].color = ItemColor::random() },
|
||||||
ArrangementFocus::Scene(s) => { self.scenes[s].color = random_color() },
|
ArrangementFocus::Scene(s) => { self.scenes[s].color = ItemColor::random() },
|
||||||
ArrangementFocus::Clip(t, s) => if let Some(phrase) = &self.scenes[s].clips[t] {
|
ArrangementFocus::Clip(t, s) => if let Some(phrase) = &self.scenes[s].clips[t] {
|
||||||
phrase.write().unwrap().color = random_color();
|
phrase.write().unwrap().color = ItemColor::random();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -396,7 +396,7 @@ impl<E: Engine> Arrangement<E> {
|
||||||
pub fn track_next (&mut self) { self.selected.track_next(self.tracks.len() - 1) }
|
pub fn track_next (&mut self) { self.selected.track_next(self.tracks.len() - 1) }
|
||||||
pub fn track_prev (&mut self) { self.selected.track_prev() }
|
pub fn track_prev (&mut self) { self.selected.track_prev() }
|
||||||
pub fn track_add (
|
pub fn track_add (
|
||||||
&mut self, name: Option<&str>, color: Option<Color>
|
&mut self, name: Option<&str>, color: Option<ItemColor>
|
||||||
) -> Usually<&mut ArrangementTrack> {
|
) -> Usually<&mut ArrangementTrack> {
|
||||||
self.tracks.push(name.map_or_else(
|
self.tracks.push(name.map_or_else(
|
||||||
|| ArrangementTrack::new(&self.clock, &self.track_default_name(), color),
|
|| ArrangementTrack::new(&self.clock, &self.track_default_name(), color),
|
||||||
|
|
@ -442,7 +442,7 @@ impl<E: Engine> Arrangement<E> {
|
||||||
pub fn scene_prev (&mut self) {
|
pub fn scene_prev (&mut self) {
|
||||||
self.selected.scene_prev()
|
self.selected.scene_prev()
|
||||||
}
|
}
|
||||||
pub fn scene_add (&mut self, name: Option<&str>, color: Option<Color>) -> Usually<&mut Scene> {
|
pub fn scene_add (&mut self, name: Option<&str>, color: Option<ItemColor>) -> Usually<&mut Scene> {
|
||||||
let clips = vec![None;self.tracks.len()];
|
let clips = vec![None;self.tracks.len()];
|
||||||
let name = name.map(|x|x.to_string()).unwrap_or_else(||self.scene_default_name());
|
let name = name.map(|x|x.to_string()).unwrap_or_else(||self.scene_default_name());
|
||||||
self.scenes.push(Scene::new(name, clips, color));
|
self.scenes.push(Scene::new(name, clips, color));
|
||||||
|
|
@ -523,11 +523,11 @@ impl<E: Engine> Arrangement<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ArrangementTrack {
|
impl ArrangementTrack {
|
||||||
pub fn new (clock: &Arc<TransportTime>, name: &str, color: Option<Color>) -> Self {
|
pub fn new (clock: &Arc<TransportTime>, name: &str, color: Option<ItemColor>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: Arc::new(RwLock::new(name.into())),
|
name: Arc::new(RwLock::new(name.into())),
|
||||||
width: name.len() + 2,
|
width: name.len() + 2,
|
||||||
color: color.unwrap_or_else(random_color),
|
color: color.unwrap_or_else(ItemColor::random),
|
||||||
player: PhrasePlayer::new(clock),
|
player: PhrasePlayer::new(clock),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -640,12 +640,12 @@ impl Scene {
|
||||||
pub fn new (
|
pub fn new (
|
||||||
name: impl AsRef<str>,
|
name: impl AsRef<str>,
|
||||||
clips: impl AsRef<[Option<Arc<RwLock<Phrase>>>]>,
|
clips: impl AsRef<[Option<Arc<RwLock<Phrase>>>]>,
|
||||||
color: Option<Color>,
|
color: Option<ItemColor>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: Arc::new(RwLock::new(name.as_ref().into())),
|
name: Arc::new(RwLock::new(name.as_ref().into())),
|
||||||
clips: clips.as_ref().iter().map(|x|x.clone()).collect(),
|
clips: clips.as_ref().iter().map(|x|x.clone()).collect(),
|
||||||
color: color.unwrap_or_else(random_color),
|
color: color.unwrap_or_else(ItemColor::random),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Returns the pulse length of the longest phrase in the scene
|
/// Returns the pulse length of the longest phrase in the scene
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ impl ArrangerCli {
|
||||||
for i in 0..self.tracks {
|
for i in 0..self.tracks {
|
||||||
let _track = arrangement.track_add(
|
let _track = arrangement.track_add(
|
||||||
None,
|
None,
|
||||||
Some(okhsl_to_rgb(track_color_1.mix(track_color_2, i as f32 / self.tracks as f32)))
|
Some(track_color_1.mix(track_color_2, i as f32 / self.tracks as f32).into())
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
let scene_color_1 = random_okhsl();
|
let scene_color_1 = random_okhsl();
|
||||||
|
|
@ -41,7 +41,7 @@ impl ArrangerCli {
|
||||||
for i in 0..self.scenes {
|
for i in 0..self.scenes {
|
||||||
let _scene = arrangement.scene_add(
|
let _scene = arrangement.scene_add(
|
||||||
None,
|
None,
|
||||||
Some(okhsl_to_rgb(scene_color_1.mix(scene_color_2, i as f32 / self.scenes as f32)))
|
Some(scene_color_1.mix(scene_color_2, i as f32 / self.scenes as f32).into())
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
let arranger = Arc::new(RwLock::new(Arranger::new(
|
let arranger = Arc::new(RwLock::new(Arranger::new(
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
.unwrap_or("(none)".into()));
|
.unwrap_or("(none)".into()));
|
||||||
col!(name, input)
|
col!(name, input)
|
||||||
.min_xy(w as u16, track_title_h)
|
.min_xy(w as u16, track_title_h)
|
||||||
.bg(track.color)
|
.bg(track.color.rgb)
|
||||||
.push_x(scene_title_w)
|
.push_x(scene_title_w)
|
||||||
});
|
});
|
||||||
// track controls
|
// track controls
|
||||||
|
|
@ -219,7 +219,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
.unwrap_or("(none)".into()));
|
.unwrap_or("(none)".into()));
|
||||||
col!(until_next, elapsed, output)
|
col!(until_next, elapsed, output)
|
||||||
.min_xy(w as u16, tracks_footer)
|
.min_xy(w as u16, tracks_footer)
|
||||||
.bg(track.color)
|
.bg(track.color.rgb)
|
||||||
.push_x(scene_title_w)
|
.push_x(scene_title_w)
|
||||||
});
|
});
|
||||||
// scene titles
|
// scene titles
|
||||||
|
|
@ -236,7 +236,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
let name = format!("{}", name);
|
let name = format!("{}", name);
|
||||||
let max_w = name.len().min((w as usize).saturating_sub(2));
|
let max_w = name.len().min((w as usize).saturating_sub(2));
|
||||||
add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?;
|
add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?;
|
||||||
color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color;
|
color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color.rgb;
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
@ -250,7 +250,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
let playing = scene.is_playing(tracks);
|
let playing = scene.is_playing(tracks);
|
||||||
Stack::right(move |add| {
|
Stack::right(move |add| {
|
||||||
// scene title:
|
// scene title:
|
||||||
add(&scene_name(scene, playing, height).bg(scene.color))?;
|
add(&scene_name(scene, playing, height).bg(scene.color.rgb))?;
|
||||||
// clip per track:
|
// clip per track:
|
||||||
Ok(for (track, w) in cols.iter().map(|col|col.0).enumerate() {
|
Ok(for (track, w) in cols.iter().map(|col|col.0).enumerate() {
|
||||||
add(&scene_clip(scene, track, w as u16, height))?;
|
add(&scene_clip(scene, track, w as u16, height))?;
|
||||||
|
|
@ -308,7 +308,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
else { area.clip_w(scene_title_w).clip_h(track_title_h) }, &CORNERS)?
|
else { area.clip_w(scene_title_w).clip_h(track_title_h) }, &CORNERS)?
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
}).bg(bg);//.grow_y(1);//.border(border);
|
}).bg(bg.rgb);//.grow_y(1);//.border(border);
|
||||||
let color = if self.0.focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)};
|
let color = if self.0.focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)};
|
||||||
let size = format!("{}x{}", self.0.size.w(), self.0.size.h());
|
let size = format!("{}x{}", self.0.size.w(), self.0.size.h());
|
||||||
let lower_right = TuiStyle::fg(size, color).pull_x(1).align_se().fill_xy();
|
let lower_right = TuiStyle::fg(size, color).pull_x(1).align_se().fill_xy();
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ pub enum PhrasePoolMode {
|
||||||
/// All notes are displayed with minimum length
|
/// All notes are displayed with minimum length
|
||||||
pub percussive: bool,
|
pub percussive: bool,
|
||||||
/// Identifying color of phrase
|
/// Identifying color of phrase
|
||||||
pub color: Color,
|
pub color: ItemColor,
|
||||||
}
|
}
|
||||||
/// Contains state for viewing and editing a phrase
|
/// Contains state for viewing and editing a phrase
|
||||||
pub struct PhraseEditor<E: Engine> {
|
pub struct PhraseEditor<E: Engine> {
|
||||||
|
|
@ -205,7 +205,7 @@ impl<E: Engine> PhrasePool<E> {
|
||||||
}
|
}
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
fn new_phrase (name: Option<&str>, color: Option<Color>) -> Arc<RwLock<Phrase>> {
|
fn new_phrase (name: Option<&str>, color: Option<ItemColor>) -> Arc<RwLock<Phrase>> {
|
||||||
Arc::new(RwLock::new(Phrase::new(
|
Arc::new(RwLock::new(Phrase::new(
|
||||||
String::from(name.unwrap_or("(new)")), true, 4 * PPQ, None, color
|
String::from(name.unwrap_or("(new)")), true, 4 * PPQ, None, color
|
||||||
)))
|
)))
|
||||||
|
|
@ -216,23 +216,23 @@ impl<E: Engine> PhrasePool<E> {
|
||||||
self.phrase = self.phrase.min(self.phrases.len().saturating_sub(1));
|
self.phrase = self.phrase.min(self.phrases.len().saturating_sub(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn append_new (&mut self, name: Option<&str>, color: Option<Color>) {
|
pub fn append_new (&mut self, name: Option<&str>, color: Option<ItemColor>) {
|
||||||
self.phrases.push(Self::new_phrase(name, color));
|
self.phrases.push(Self::new_phrase(name, color));
|
||||||
self.phrase = self.phrases.len() - 1;
|
self.phrase = self.phrases.len() - 1;
|
||||||
}
|
}
|
||||||
pub fn insert_new (&mut self, name: Option<&str>, color: Option<Color>) {
|
pub fn insert_new (&mut self, name: Option<&str>, color: Option<ItemColor>) {
|
||||||
self.phrases.insert(self.phrase + 1, Self::new_phrase(name, color));
|
self.phrases.insert(self.phrase + 1, Self::new_phrase(name, color));
|
||||||
self.phrase += 1;
|
self.phrase += 1;
|
||||||
}
|
}
|
||||||
pub fn insert_dup (&mut self) {
|
pub fn insert_dup (&mut self) {
|
||||||
let mut phrase = self.phrases[self.phrase].read().unwrap().duplicate();
|
let mut phrase = self.phrases[self.phrase].read().unwrap().duplicate();
|
||||||
phrase.color = random_color_near(phrase.color, 0.25);
|
phrase.color = ItemColor::random_near(phrase.color, 0.25);
|
||||||
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
||||||
self.phrase += 1;
|
self.phrase += 1;
|
||||||
}
|
}
|
||||||
pub fn randomize_color (&mut self) {
|
pub fn randomize_color (&mut self) {
|
||||||
let mut phrase = self.phrases[self.phrase].write().unwrap();
|
let mut phrase = self.phrases[self.phrase].write().unwrap();
|
||||||
phrase.color = random_color();
|
phrase.color = ItemColor::random();
|
||||||
}
|
}
|
||||||
pub fn begin_rename (&mut self) {
|
pub fn begin_rename (&mut self) {
|
||||||
self.mode = Some(PhrasePoolMode::Rename(
|
self.mode = Some(PhrasePoolMode::Rename(
|
||||||
|
|
@ -347,7 +347,7 @@ impl Phrase {
|
||||||
loop_on: bool,
|
loop_on: bool,
|
||||||
length: usize,
|
length: usize,
|
||||||
notes: Option<PhraseData>,
|
notes: Option<PhraseData>,
|
||||||
color: Option<Color>,
|
color: Option<ItemColor>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
uuid: uuid::Uuid::new_v4(),
|
uuid: uuid::Uuid::new_v4(),
|
||||||
|
|
@ -359,7 +359,7 @@ impl Phrase {
|
||||||
loop_start: 0,
|
loop_start: 0,
|
||||||
loop_length: length,
|
loop_length: length,
|
||||||
percussive: true,
|
percussive: true,
|
||||||
color: color.unwrap_or_else(random_color)
|
color: color.unwrap_or_else(ItemColor::random)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn duplicate (&self) -> Self {
|
pub fn duplicate (&self) -> Self {
|
||||||
|
|
@ -384,7 +384,7 @@ impl Phrase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Default for Phrase {
|
impl Default for Phrase {
|
||||||
fn default () -> Self { Self::new("(empty)", false, 0, None, Some(Color::Rgb(0, 0, 0))) }
|
fn default () -> Self { Self::new("(empty)", false, 0, None, Some(Color::Rgb(0, 0, 0).into())) }
|
||||||
}
|
}
|
||||||
impl PartialEq for Phrase { fn eq (&self, other: &Self) -> bool { self.uuid == other.uuid } }
|
impl PartialEq for Phrase { fn eq (&self, other: &Self) -> bool { self.uuid == other.uuid } }
|
||||||
impl Eq for Phrase {}
|
impl Eq for Phrase {}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ impl Content for PhrasePool<Tui> {
|
||||||
};
|
};
|
||||||
let row2 = TuiStyle::bold(row2, true);
|
let row2 = TuiStyle::bold(row2, true);
|
||||||
let bg = if i == self.phrase { color } else { color };
|
let bg = if i == self.phrase { color } else { color };
|
||||||
add(&col!(row1, row2).fill_x().bg(bg))?;
|
add(&col!(row1, row2).fill_x().bg(bg.rgb))?;
|
||||||
Ok(if *focused && i == self.phrase { add(&CORNERS)?; })
|
Ok(if *focused && i == self.phrase { add(&CORNERS)?; })
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -57,7 +57,7 @@ impl Content for PhraseEditor<Tui> {
|
||||||
start: time_start, point: time_point, clamp: time_clamp, scale: time_scale
|
start: time_start, point: time_point, clamp: time_clamp, scale: time_scale
|
||||||
} = *self.time_axis.read().unwrap();
|
} = *self.time_axis.read().unwrap();
|
||||||
let color = Color::Rgb(0,255,0);
|
let color = Color::Rgb(0,255,0);
|
||||||
let color = phrase.as_ref().map(|p|p.read().unwrap().color).unwrap_or(color);
|
let color = phrase.as_ref().map(|p|p.read().unwrap().color.rgb).unwrap_or(color);
|
||||||
let keys = CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(5))), move|to: &mut TuiOutput|{
|
let keys = CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(5))), move|to: &mut TuiOutput|{
|
||||||
Ok(if to.area().h() >= 2 {
|
Ok(if to.area().h() >= 2 {
|
||||||
to.buffer_update(to.area().set_w(5), &|cell, x, y|{
|
to.buffer_update(to.area().set_w(5), &|cell, x, y|{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue