From 11de96db58bfe8a95836d94fbd2ea8561d8281ed Mon Sep 17 00:00:00 2001 From: Tarasov Aleksandr <55220741+arabianq@users.noreply.github.com> Date: Mon, 27 Apr 2026 23:05:39 +0300 Subject: [PATCH] refactor: simplify `draw_track_control` by extracting helper functions (#87) Extracted distinct UI sections (playback controls, position slider, volume controls, stop button) into their own well-scoped helper functions within `SoundpadGui`. This significantly improves the maintainability and readability of `draw_track_control` while preserving the existing layout structure and state mutation behavior. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- src/gui/draw.rs | 183 ++++++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 83 deletions(-) diff --git a/src/gui/draw.rs b/src/gui/draw.rs index 8455aca..db4e3c2 100644 --- a/src/gui/draw.rs +++ b/src/gui/draw.rs @@ -444,6 +444,99 @@ impl SoundpadGui { }); } + fn draw_playback_controls(ui: &mut Ui, track: &TrackInfo) -> Option { + let mut action = None; + + let play_button = Button::new(if track.paused { + ICON_PLAY_ARROW + } else { + ICON_PAUSE + }) + .corner_radius(15.0); + + if ui.add_sized([30.0, 30.0], play_button).clicked() { + action = Some(if track.paused { + TrackAction::Resume(track.id) + } else { + TrackAction::Pause(track.id) + }); + } + + let loop_button = Button::new( + RichText::new(if track.looped { + ICON_REPEAT_ONE + } else { + ICON_REPEAT + }) + .size(18.0), + ) + .frame(false); + + if ui.add_sized([15.0, 30.0], loop_button).clicked() { + action = Some(TrackAction::ToggleLoop(track.id)); + } + + action + } + + fn draw_position_control( + ui: &mut Ui, + ui_state: &mut pwsp::types::gui::TrackUiState, + track: &TrackInfo, + default_slider_width: f32, + ) { + let duration = track.duration.unwrap_or(1.0); + let position_slider = Slider::new(&mut ui_state.position_slider_value, 0.0..=duration) + .show_value(false) + .step_by(0.01); + + let position_slider_width = ui.available_width() + - (30.0 * 3.0) + - default_slider_width + - (ui.spacing().item_spacing.x * 6.0); + + ui.spacing_mut().slider_width = position_slider_width; + if ui.add_sized([30.0, 30.0], position_slider).drag_stopped() { + ui_state.position_dragged = true; + } + + let time_label = + Label::new(RichText::new(format_time_pair(track.position, duration)).monospace()); + ui.add_sized([30.0, 30.0], time_label); + } + + fn draw_volume_control( + ui: &mut Ui, + ui_state: &mut pwsp::types::gui::TrackUiState, + track: &TrackInfo, + default_slider_width: f32, + ) { + let volume_icon = Self::get_volume_icon(track.volume); + let volume_label = Label::new(RichText::new(volume_icon).size(18.0)); + ui.add_sized([30.0, 30.0], volume_label) + .on_hover_text(format!("Volume: {:.0}%", track.volume * 100.0)); + + let volume_slider = Slider::new(&mut ui_state.volume_slider_value, 0.0..=1.0) + .show_value(false) + .step_by(0.01); + + ui.spacing_mut().slider_width = default_slider_width - 30.0; + ui.spacing_mut().item_spacing.x = 0.0; + + if ui.add_sized([30.0, 30.0], volume_slider).drag_stopped() { + ui_state.volume_dragged = true; + } + } + + fn draw_stop_control(ui: &mut Ui, track: &TrackInfo) -> Option { + let stop_button = Button::new(ICON_CLOSE).frame(false); + if ui.add_sized([30.0, 30.0], stop_button).clicked() { + Some(TrackAction::Stop(track.id)) + } else { + None + } + } + fn draw_track_control( ui: &mut Ui, app_state: &mut AppState, @@ -474,93 +567,17 @@ impl SoundpadGui { let mut action = None; ui.horizontal_top(|ui| { - // ---------- Play Button ---------- - let play_button = Button::new(if track.paused { - ICON_PLAY_ARROW - } else { - ICON_PAUSE - }) - .corner_radius(15.0); - - let play_button_response = ui.add_sized([30.0, 30.0], play_button); - if play_button_response.clicked() { - if track.paused { - action = Some(TrackAction::Resume(track.id)); - } else { - action = Some(TrackAction::Pause(track.id)); - } + if let Some(act) = Self::draw_playback_controls(ui, track) { + action = Some(act); } - // -------------------------------- - - // ---------- Loop Button ---------- - let loop_button = Button::new( - RichText::new(if track.looped { - ICON_REPEAT_ONE - } else { - ICON_REPEAT - }) - .size(18.0), - ) - .frame(false); - - let loop_button_response = ui.add_sized([15.0, 30.0], loop_button); - if loop_button_response.clicked() { - action = Some(TrackAction::ToggleLoop(track.id)); - } - // -------------------------------- - - // ---------- Position Slider ---------- - let duration = track.duration.unwrap_or(1.0); - let position_slider = Slider::new(&mut ui_state.position_slider_value, 0.0..=duration) - .show_value(false) - .step_by(0.01); let default_slider_width = ui.spacing().slider_width; - let position_slider_width = ui.available_width() - - (30.0 * 3.0) - - default_slider_width - - (ui.spacing().item_spacing.x * 6.0); - ui.spacing_mut().slider_width = position_slider_width; - let position_slider_response = ui.add_sized([30.0, 30.0], position_slider); - if position_slider_response.drag_stopped() { - ui_state.position_dragged = true; + Self::draw_position_control(ui, ui_state, track, default_slider_width); + Self::draw_volume_control(ui, ui_state, track, default_slider_width); + + if let Some(act) = Self::draw_stop_control(ui, track) { + action = Some(act); } - // -------------------------------- - - // ---------- Time Label ---------- - let time_label = - Label::new(RichText::new(format_time_pair(track.position, duration)).monospace()); - ui.add_sized([30.0, 30.0], time_label); - // -------------------------------- - - // ---------- Volume Icon ---------- - let volume_icon = Self::get_volume_icon(track.volume); - let volume_label = Label::new(RichText::new(volume_icon).size(18.0)); - ui.add_sized([30.0, 30.0], volume_label) - .on_hover_text(format!("Volume: {:.0}%", track.volume * 100.0)); - // -------------------------------- - - // ---------- Volume Slider ---------- - let volume_slider = Slider::new(&mut ui_state.volume_slider_value, 0.0..=1.0) - .show_value(false) - .step_by(0.01); - - ui.spacing_mut().slider_width = default_slider_width - 30.0; - ui.spacing_mut().item_spacing.x = 0.0; - - let volume_slider_response = ui.add_sized([30.0, 30.0], volume_slider); - if volume_slider_response.drag_stopped() { - ui_state.volume_dragged = true; - } - // -------------------------------- - - // ---------- Stop Button --------- - let stop_button = Button::new(ICON_CLOSE).frame(false); - let stop_button_response = ui.add_sized([30.0, 30.0], stop_button); - if stop_button_response.clicked() { - action = Some(TrackAction::Stop(track.id)); - } - // -------------------------------- }); action