From: Huck Boles Date: Sat, 8 Jul 2023 22:32:20 +0000 (-0500) Subject: fixed: gui alignment issues X-Git-Url: https://git.huck.website/?a=commitdiff_plain;h=76a74d829263b7f001ce51117202674e23bf208b;p=cellseq.git fixed: gui alignment issues --- diff --git a/src/display.rs b/src/display.rs index 9484002..8e50f64 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,7 +1,9 @@ use iced::{ + alignment::{Horizontal, Vertical}, theme, widget::{ - button, checkbox, column, pick_list, row, slider, text, vertical_slider, Column, Row, + button, checkbox, column, container, horizontal_space, pick_list, row, slider, text, + vertical_slider, vertical_space, }, Alignment, Element, Length, }; @@ -19,251 +21,266 @@ pub struct ControlMessage { } pub fn top_controls<'a>(is_playing: bool) -> Element<'a, Message> { - let play_button = row![ - button(if is_playing { "stop" } else { "play" }).on_press(Message::TogglePlayback), - button("save map") - .on_press(Message::Save) - .style(theme::Button::Positive), - button("reset map") - .on_press(Message::Reset) - .style(theme::Button::Secondary), - button("clear map") - .on_press(Message::ClearMap) - .style(theme::Button::Destructive), - button("clear mask") - .on_press(Message::ClearMask) - .style(theme::Button::Destructive), - ] - .width(Length::Fill) - .spacing(10); + let play_button = container( + row![ + button(if is_playing { "stop" } else { "play" }).on_press(Message::TogglePlayback), + button("save map") + .on_press(Message::Save) + .style(theme::Button::Positive), + button("reset map") + .on_press(Message::Reset) + .style(theme::Button::Secondary), + button("clear map") + .on_press(Message::ClearMap) + .style(theme::Button::Destructive), + button("clear mask") + .on_press(Message::ClearMask) + .style(theme::Button::Destructive), + ] + .spacing(10), + ) + .align_x(Horizontal::Left); - let other_controls = row![button("quit") - .on_press(Message::Quit) - .style(theme::Button::Destructive),] - .width(Length::Fill) - .align_items(Alignment::End) - .spacing(10); + let other_controls = container( + button("quit") + .on_press(Message::Quit) + .style(theme::Button::Destructive), + ) + .align_x(Horizontal::Right); - row![play_button, other_controls] - .width(Length::Fill) + container(row![play_button, horizontal_space(Length::Fill), other_controls].width(Length::Fill)) .padding(10) - .spacing(40) + .align_y(Vertical::Top) .into() } pub fn bottom_controls<'a>(message: ControlMessage) -> Element<'a, Message> { - column![ - map_section(&message), - probability_section(&message).width(Length::Fixed(600.0)), - scale_selector(&message), - music_controls(&message) - ] - .width(Length::Fill) - .height(Length::Fill) - .padding(10) - .spacing(20) - .align_items(Alignment::Center) - .into() -} - -fn music_controls<'a>(message: &ControlMessage) -> Row<'a, Message> { - row![ - song_section(message), - midi_section(message), - velocity_sliders(message) - ] - .height(Length::Fill) - .padding(10) - .spacing(40) + container( + column![ + randomize_section(message.randomness), + vertical_space(40), + music_controls(message) + ] + .align_items(Alignment::Center) + .padding(10) + .spacing(20), + ) + .align_x(Horizontal::Center) .into() } -fn song_section<'a>(message: &ControlMessage) -> Row<'a, Message> { - row![song_params(), song_vals(message)] - .height(Length::Fill) +fn music_controls<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + row![ + column![ + scale_selector(message), + row![song_section(message), midi_section(message),] + .padding(10) + .spacing(40), + ] + .align_items(Alignment::Center), + velocity_sliders(message) + ] .padding(10) - .spacing(20) - .into() + .spacing(40), + ) + .into() } -fn midi_section<'a>(message: &ControlMessage) -> Row<'a, Message> { - row![midi_params(), midi_vals(message)] - .height(Length::Fill) - .padding(10) - .spacing(20) - .into() +fn song_section<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + row![song_params(), song_vals(message)] + .padding(10) + .spacing(10), + ) + .into() } -fn song_params<'a>() -> Column<'a, Message> { - column![ - text("loop section"), - text("number of steps"), - text("bpm"), - text("note division"), - ] - .height(Length::Fill) - .padding(10) - .spacing(20) +fn midi_section<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + row![midi_params(), midi_vals(message)] + .padding(10) + .spacing(10), + ) .into() } -fn song_vals<'a>(message: &ControlMessage) -> Column<'a, Message> { - column![ - checkbox("", message.song.is_looping, |_| { Message::ToggleLoop }), - row![ - button("-").on_press(Message::LoopLength(message.song.loop_len.saturating_sub(1))), - text(if message.song.is_looping { - format!("{}/{}", message.song.step_num, message.song.loop_len) - } else { - format!("{}", message.song.loop_len) - }), - button("+").on_press(Message::LoopLength(message.song.loop_len.saturating_add(1))), - ], - row![ - button("-").on_press(Message::SpeedChanged(message.song.bpm.saturating_sub(1))), - text(format!("{}", message.song.bpm)), - button("+").on_press(Message::SpeedChanged(message.song.bpm.saturating_add(1))), - ], - row![ - button("-").on_press(Message::NewDivision(message.song.divisor.saturating_sub(1))), - text(format!("{}", message.song.divisor)), - button("+").on_press(Message::NewDivision(message.song.divisor.saturating_add(1))), +fn song_params<'a>() -> Element<'a, Message> { + container( + column![ + text("bpm"), + text("note division"), + text("number of steps"), + text("loop section"), ] - ] - .height(Length::Fill) - .padding(10) - .spacing(20) + .align_items(Alignment::End) + .padding(10) + .spacing(30), + ) .into() } -fn midi_params<'a>() -> Column<'a, Message> { - column![ - text("center octave"), - text("octave range"), - text("number of voices"), - text("midi channel"), - ] - .height(Length::Fill) - .padding(10) - .spacing(20) +fn song_vals<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + column![ + row![ + button("-").on_press(Message::SpeedChanged(message.song.bpm.saturating_sub(1))), + text(format!("{}", message.song.bpm)), + button("+").on_press(Message::SpeedChanged(message.song.bpm.saturating_add(1))), + ] + .align_items(Alignment::Center) + .spacing(10), + row![ + button("-").on_press(Message::NewDivision(message.song.divisor.saturating_sub(1))), + text(format!("{}", message.song.divisor)), + button("+").on_press(Message::NewDivision(message.song.divisor.saturating_add(1))), + ] + .align_items(Alignment::Center) + .spacing(10), + row![ + button("-").on_press(Message::LoopLength(message.song.loop_len.saturating_sub(1))), + text(if message.song.is_looping { + format!("{}/{}", message.song.step_num, message.song.loop_len) + } else { + format!("{}", message.song.loop_len) + }), + button("+").on_press(Message::LoopLength(message.song.loop_len.saturating_add(1))), + ] + .align_items(Alignment::Center) + .spacing(10), + checkbox("", message.song.is_looping, |_| { Message::ToggleLoop }), + ] + .align_items(Alignment::Center) + .padding(10) + .spacing(20), + ) .into() } -fn midi_vals<'a>(message: &ControlMessage) -> Column<'a, Message> { - column![ - row![ - button("-").on_press(Message::NewOctave( - message.info.octave.center.saturating_sub(1) - )), - text(format!("{}", message.info.octave.center)), - button("+").on_press(Message::NewOctave( - message.info.octave.center.saturating_add(1) - )), - ], - row![ - button("-").on_press(Message::OctaveRange( - message.info.octave.range.saturating_sub(1) - )), - text(format!("{}", message.info.octave.range)), - button("+").on_press(Message::OctaveRange( - message.info.octave.range.saturating_add(1) - )), - ], - row![ - button("-").on_press(Message::Voices(message.info.voices.saturating_sub(1))), - text(format!("{}", message.info.voices)), - button("+").on_press(Message::Voices(message.info.voices.saturating_add(1))), - ], - row![ - button("-").on_press(Message::ChannelChange( - message.info.channel.saturating_sub(1) - )), - text(format!("{}", message.info.channel)), - button("+").on_press(Message::ChannelChange( - message.info.channel.saturating_add(1) - )), +fn midi_params<'a>() -> Element<'a, Message> { + container( + column![ + text("center octave"), + text("octave range"), + text("number of voices"), + text("midi channel"), ] - ] - .height(Length::Fill) - .padding(10) - .spacing(20) + .align_items(Alignment::End) + .padding(10) + .spacing(30), + ) .into() } -fn map_section<'a>(message: &ControlMessage) -> Row<'a, Message> { - row![ - map_buttons(), - randomize_section(message.randomness).width(Length::Fixed(500.0)) - ] - .spacing(10) -} - -fn probability_section<'a>(message: &ControlMessage) -> Row<'a, Message> { - row![ - text("probability a cell triggers a note"), - slider(0.0..=100.0, message.info.probability * 100.0, |x| { - Message::ProbChanged(x / 100.0) - }), - text(format!("{}", message.info.probability)), - ] - .spacing(10) -} - -fn randomize_section<'a>(r: f32) -> Row<'a, Message> { - row![ - slider(0.0..=100.0, r * 100.0, |x| { - Message::RandChanged(x / 100.0) - }), - text(format!("{r}")), - ] - .spacing(10) +fn midi_vals<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + column![ + row![ + button("-").on_press(Message::NewOctave( + message.info.octave.center.saturating_sub(1) + )), + text(format!("{}", message.info.octave.center)), + button("+").on_press(Message::NewOctave( + message.info.octave.center.saturating_add(1) + )), + ] + .spacing(10), + row![ + button("-").on_press(Message::OctaveRange( + message.info.octave.range.saturating_sub(1) + )), + text(format!("{}", message.info.octave.range)), + button("+").on_press(Message::OctaveRange( + message.info.octave.range.saturating_add(1) + )), + ] + .spacing(10), + row![ + button("-").on_press(Message::Voices(message.info.voices.saturating_sub(1))), + text(format!("{}", message.info.voices)), + button("+").on_press(Message::Voices(message.info.voices.saturating_add(1))), + ] + .spacing(10), + row![ + button("-").on_press(Message::ChannelChange( + message.info.channel.saturating_sub(1) + )), + text(format!("{}", message.info.channel)), + button("+").on_press(Message::ChannelChange( + message.info.channel.saturating_add(1) + )), + ] + .spacing(10) + ] + .align_items(Alignment::Center) + .padding(10) + .spacing(20), + ) + .into() } -fn map_buttons<'a>() -> Row<'a, Message> { - row![ - button("randomize map") - .on_press(Message::RandomizeMap) - .style(theme::Button::Primary), - button("randomize mask") - .on_press(Message::RandomizeMask) - .style(theme::Button::Primary), - ] - .spacing(10) +fn randomize_section<'a>(r: f32) -> Element<'a, Message> { + container( + row![ + button("randomize map") + .on_press(Message::RandomizeMap) + .style(theme::Button::Primary), + slider(0.0..=100.0, r * 100.0, |x| { + Message::RandChanged(x / 100.0) + }) + .width(Length::Fixed(300.0)), + text(format!("{r}")), + button("randomize mask") + .on_press(Message::RandomizeMask) + .style(theme::Button::Primary), + ] + .spacing(20), + ) + .into() } -fn velocity_sliders<'a>(message: &ControlMessage) -> Column<'a, Message> { - column![ - text("velocity range"), - row![ - column![ - text(format!("{}", message.info.velocity.max())), - vertical_slider(0..=127, message.info.velocity.max(), Message::NewVMax), - text("max") - ], - column![ - text(format!("{}", message.info.velocity.min())), - vertical_slider(0..=127, message.info.velocity.min(), Message::NewVMin), - text("min") - ], +fn velocity_sliders<'a>(message: ControlMessage) -> Element<'a, Message> { + container( + column![ + text("velocity range"), + row![ + column![ + text(format!("{}", message.info.velocity.max())), + vertical_slider(0..=127, message.info.velocity.max(), Message::NewVMax), + text("max") + ], + column![ + text(format!("{}", message.info.velocity.min())), + vertical_slider(0..=127, message.info.velocity.min(), Message::NewVMin), + text("min") + ], + ] + .spacing(20.0) ] - ] - .spacing(10) + .height(Length::Fixed(300.0)) + .spacing(10), + ) + .into() } -fn scale_selector<'a>(message: &ControlMessage) -> Row<'a, Message> { +fn scale_selector<'a>(message: ControlMessage) -> Element<'a, Message> { let scale = message.info.scale; let note = message.info.root.note; let accidental = message.info.root.accidental; - row![ - pick_list(&RootNote::ALL[..], Some(note), move |note| { - Message::NewNote(Root { note, accidental }) - }) - .width(Length::Fixed(50.0)), - pick_list(&Accidental::ALL[..], Some(accidental), move |accidental| { - Message::NewNote(Root { note, accidental }) - }) - .width(Length::Fixed(90.0)), - pick_list(&Scale::ALL[..], Some(scale), Message::Scale).width(Length::Fixed(160.0)), - ] - .align_items(Alignment::Center) + container( + row![ + pick_list(&RootNote::ALL[..], Some(note), move |note| { + Message::NewNote(Root { note, accidental }) + }) + .width(Length::Fixed(50.0)), + pick_list(&Accidental::ALL[..], Some(accidental), move |accidental| { + Message::NewNote(Root { note, accidental }) + }) + .width(Length::Fixed(90.0)), + pick_list(&Scale::ALL[..], Some(scale), Message::Scale).width(Length::Fixed(160.0)), + ] + .spacing(10), + ) + .align_x(Horizontal::Center) + .into() } diff --git a/src/lib.rs b/src/lib.rs index ba7430f..af6b704 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,10 @@ use iced::{ + alignment::{Horizontal, Vertical}, executor, theme::Theme, time, - widget::{column, container, row}, - window, {Alignment, Application, Command, Element, Length, Point, Subscription}, + widget::{column, container, row, text, vertical_slider, vertical_space}, + window, Alignment, {Application, Command, Element, Length, Point, Subscription}, }; use itertools::Itertools; @@ -162,7 +163,7 @@ impl Application for CellSeq { return Command::perform(async move { hits }, Message::HitCount); } Message::Tick(_) => { - let map = if self.song.is_looping && self.song.step_num > self.song.loop_len { + let map = if self.song.is_looping && self.song.step_num >= self.song.loop_len { self.song.step_num = 0; self.map.reset_loop() } else { @@ -242,23 +243,41 @@ impl Application for CellSeq { fn view(&self) -> Element { let top = top_controls(self.song.is_playing); - let map = row![ - self.map.view().map(Message::MapMessage), - self.mask.view().map(Message::MaskMessage) - ] - .width(Length::Fill) - .height(Length::Fill) - .align_items(Alignment::Center) - .spacing(40); + let probability_slider = container( + column![ + text(format!("{}", self.info.probability)), + vertical_slider(0.0..=100.0, self.info.probability * 100.0, |x| { + Message::ProbChanged(x / 100.0) + }), + text("note density") + ] + .height(Length::Fixed(350.0)) + .align_items(Alignment::Center), + ) + .align_y(Vertical::Top); + + let map = container( + row![ + self.map.view().map(Message::MapMessage), + probability_slider, + self.mask.view().map(Message::MaskMessage) + ] + .padding(10) + .spacing(20), + ) + .align_x(Horizontal::Center); let bottom = bottom_controls(self.control_message()); - let content = column![top, map, bottom].width(Length::Fill); - - container(content) - .width(Length::Fill) - .height(Length::Fill) - .into() + container( + column![top, vertical_space(40), map, bottom] + .width(Length::Fill) + .align_items(Alignment::Center), + ) + .align_x(Horizontal::Center) + .width(Length::Fill) + .height(Length::Fill) + .into() } fn theme(&self) -> Theme {