summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Elliott <pelliott@ualberta.ca>2020-10-11 13:26:57 -0600
committerAndreas Kling <kling@serenityos.org>2020-10-12 19:41:53 +0200
commitb82f2df4c8f135677f186e2133090d2ac97016c9 (patch)
treea915ec374a16ed9aca49e5ec08c1da1fbcc34b03
parent27b990ec19f490e078e6c19ca803fd80cb13d185 (diff)
downloadserenity-b82f2df4c8f135677f186e2133090d2ac97016c9.zip
Piano: Add UI support for different lengths of notes
-rw-r--r--Applications/Piano/RollWidget.cpp63
-rw-r--r--Applications/Piano/RollWidget.h6
-rw-r--r--Applications/Piano/Track.cpp8
3 files changed, 53 insertions, 24 deletions
diff --git a/Applications/Piano/RollWidget.cpp b/Applications/Piano/RollWidget.cpp
index d8d0aa670e..9d99f1b67c 100644
--- a/Applications/Piano/RollWidget.cpp
+++ b/Applications/Piano/RollWidget.cpp
@@ -159,29 +159,58 @@ void RollWidget::mousedown_event(GUI::MouseEvent& event)
if (!widget_inner_rect().contains(event.x(), event.y()))
return;
- int y = (event.y() + vertical_scrollbar().value()) - frame_thickness();
+ m_note_drag_start = event.position();
+
+ int y = (m_note_drag_start.value().y() + vertical_scrollbar().value()) - frame_thickness();
y /= note_height;
+ m_drag_note = (note_count - 1) - y;
+
+ mousemove_event(event);
+}
- // There's a case where we can't just use x / m_note_width. For example, if
- // your m_note_width is 3.1 you will have a rect starting at 3. When that
- // leftmost pixel of the rect is clicked you will do 3 / 3.1 which is 0
- // and not 1. We can avoid that case by shifting x by 1 if m_note_width is
- // fractional, being careful not to shift out of bounds.
- int x = (event.x() + horizontal_scrollbar().value()) - frame_thickness();
- bool note_width_is_fractional = m_note_width - static_cast<int>(m_note_width) != 0;
- bool x_is_not_last = x != widget_inner_rect().width() - 1;
- if (note_width_is_fractional && x_is_not_last)
- ++x;
- x /= m_note_width;
-
- int note = (note_count - 1) - y;
- u32 on_sample = roll_length * (static_cast<double>(x) / m_num_notes);
- u32 off_sample = (roll_length * (static_cast<double>(x + 1) / m_num_notes)) - 1;
- m_track_manager.current_track().set_roll_note(note, on_sample, off_sample);
+void RollWidget::mousemove_event(GUI::MouseEvent& event)
+{
+ if (!m_note_drag_start.has_value())
+ return;
+
+ if (m_note_drag_location.has_value()) {
+ // Clear previous note
+ m_track_manager.current_track().set_roll_note(m_drag_note, m_note_drag_location.value().on_sample, m_note_drag_location.value().off_sample);
+ }
+
+ auto get_note_x = [&](int x0) {
+ // There's a case where we can't just use x / m_note_width. For example, if
+ // your m_note_width is 3.1 you will have a rect starting at 3. When that
+ // leftmost pixel of the rect is clicked you will do 3 / 3.1 which is 0
+ // and not 1. We can avoid that case by shifting x by 1 if m_note_width is
+ // fractional, being careful not to shift out of bounds.
+ int x = (x0 + horizontal_scrollbar().value()) - frame_thickness();
+ bool note_width_is_fractional = m_note_width - static_cast<int>(m_note_width) != 0;
+ bool x_is_not_last = x != widget_inner_rect().width() - 1;
+ if (note_width_is_fractional && x_is_not_last)
+ ++x;
+ x /= m_note_width;
+ return x;
+ };
+
+ int x0 = get_note_x(m_note_drag_start.value().x());
+ int x1 = get_note_x(event.x());
+
+ u32 on_sample = roll_length * (static_cast<double>(min(x0, x1)) / m_num_notes);
+ u32 off_sample = (roll_length * (static_cast<double>(max(x0, x1) + 1) / m_num_notes)) - 1;
+ m_track_manager.current_track().set_roll_note(m_drag_note, on_sample, off_sample);
+ m_note_drag_location = RollNote({ on_sample, off_sample });
update();
}
+void RollWidget::mouseup_event(GUI::MouseEvent& event)
+{
+ (void)event;
+ m_note_drag_start = {};
+ m_note_drag_location = {};
+}
+
// FIXME: Implement zoom and horizontal scroll events in LibGUI, not here.
void RollWidget::mousewheel_event(GUI::MouseEvent& event)
{
diff --git a/Applications/Piano/RollWidget.h b/Applications/Piano/RollWidget.h
index 28910156cc..bbfcc8bb62 100644
--- a/Applications/Piano/RollWidget.h
+++ b/Applications/Piano/RollWidget.h
@@ -46,6 +46,8 @@ private:
virtual void paint_event(GUI::PaintEvent&) override;
virtual void mousedown_event(GUI::MouseEvent& event) override;
+ virtual void mousemove_event(GUI::MouseEvent& event) override;
+ virtual void mouseup_event(GUI::MouseEvent& event) override;
virtual void mousewheel_event(GUI::MouseEvent&) override;
TrackManager& m_track_manager;
@@ -55,4 +57,8 @@ private:
int m_num_notes { 0 };
double m_note_width { 0.0 };
int m_zoom_level { 1 };
+
+ Optional<Gfx::IntPoint> m_note_drag_start;
+ Optional<RollNote> m_note_drag_location;
+ int m_drag_note;
};
diff --git a/Applications/Piano/Track.cpp b/Applications/Piano/Track.cpp
index 22cbbe03f8..754a43407a 100644
--- a/Applications/Piano/Track.cpp
+++ b/Applications/Piano/Track.cpp
@@ -287,7 +287,7 @@ void Track::set_roll_note(int note, u32 on_sample, u32 off_sample)
sync_roll(note);
return;
}
- if (it->on_sample == new_roll_note.on_sample && it->off_sample == new_roll_note.off_sample) {
+ if (it->on_sample <= new_roll_note.on_sample && it->off_sample >= new_roll_note.on_sample) {
if (m_time >= it->on_sample && m_time <= it->off_sample)
set_note(note, Off);
m_roll_notes[note].remove(it);
@@ -301,12 +301,6 @@ void Track::set_roll_note(int note, u32 on_sample, u32 off_sample)
it = m_roll_notes[note].begin();
continue;
}
- if (it->on_sample < new_roll_note.on_sample && it->off_sample >= new_roll_note.on_sample) {
- if (m_time >= new_roll_note.off_sample && m_time <= it->off_sample)
- set_note(note, Off);
- it->off_sample = new_roll_note.on_sample - 1;
- ASSERT(it->length() >= 2);
- }
++it;
}