Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
piano_roll_view.hpp
Go to the documentation of this file.
1#pragma once
2
6
12#include <pulp/view/view.hpp>
13
14#include <cstddef>
15#include <functional>
16#include <optional>
17#include <span>
18#include <vector>
19
20namespace pulp::timeline_view {
21
25
42
58
62enum class PianoRollRefusal : std::uint8_t {
70};
71
89class PianoRollView : public view::View {
90 public:
97 using NoteFactory = std::function<std::optional<timeline::NoteEvent>(
98 timebase::TickPosition start, std::uint8_t pitch)>;
99
101
109 void set_clip(const timeline::Project* project, timeline::ItemId sequence_id,
110 timeline::ItemId track_id, timeline::ItemId clip_id);
111 void set_layout(const PianoRollLayout& layout);
123 void set_continuous_gestures(bool enabled) noexcept { continuous_gestures_ = enabled; }
124
126 std::span<const timeline::NoteEvent> notes() const;
127
130 std::optional<view::Rect> note_rect(timeline::ItemId note_id) const;
131
137 std::size_t painted_note_count() const noexcept { return painted_note_count_; }
138
144 std::size_t visited_candidate_count() const noexcept { return visited_candidate_count_; }
145
147 const std::vector<PianoRollRefusal>& refusals() const noexcept { return refusals_; }
148 void clear_refusals() { refusals_.clear(); }
149
152 bool gesture_open() const noexcept { return drag_.has_value(); }
153
154 // ── View ─────────────────────────────────────────────────────────────
155
156 void paint(canvas::Canvas& canvas) override;
157 bool wants_mouse_input() const override { return true; }
165 void on_mouse_event(const view::MouseEvent& event) override;
166
167 private:
169 enum class DragKind : std::uint8_t {
170 Insert,
171 Move,
172 Resize,
173 SetVelocity,
174 };
175
179 struct Drag {
180 DragKind kind = DragKind::Move;
182 std::optional<timeline::NoteEvent> grabbed;
186 std::int64_t grab_offset_ticks = 0;
189 timebase::TickPosition press_tick{};
190 std::uint8_t press_pitch = 60;
191 float press_y = 0.0f;
193 std::optional<timeline::NoteEvent> pending;
195 std::optional<timeline::NoteEvent> last_emitted;
198 std::optional<timeline::NoteEvent> last_refused;
201 bool release_only = false;
202 };
203
204 const timeline::MidiContent* content() const;
207 const timeline::NoteEvent* note_at(view::Point position) const;
210 bool on_trailing_edge(const timeline::NoteEvent& note, view::Point position) const;
211
213 timebase::TickPosition snapped(timebase::TickPosition tick) const;
216 bool admissible(const timeline::NoteEvent& note);
218 std::optional<timeline::NoteEvent> replacement_at(const Drag& drag,
219 view::Point position) const;
220
222 std::optional<timeline::NoteEvent> expected,
223 std::optional<timeline::NoteEvent> replacement);
224
225 const timeline::Project* project_ = nullptr;
226 timeline::ItemId sequence_id_{};
227 timeline::ItemId track_id_{};
228 timeline::ItemId clip_id_{};
229 std::optional<PianoRollLayout> layout_;
231 view::HitMetrics metrics_ = view::HitMetrics::for_pointer(view::PointerType::mouse);
232 NoteFactory note_factory_;
233 std::optional<Drag> drag_;
234 std::uint16_t current_modifiers_ = view::kModNone;
235 bool continuous_gestures_ = false;
236 std::vector<PianoRollRefusal> refusals_;
241 std::vector<timebase::TickPosition> note_interval_max_end_;
242 std::size_t painted_note_count_ = 0;
243 std::size_t visited_candidate_count_ = 0;
244};
245
247
248} // namespace pulp::timeline_view
Definition canvas.hpp:240
Immutable root of a Timeline document and its monotonic identity domain.
Definition model.hpp:1079
Projects an inclusive MIDI pitch range onto piano-roll rows.
Definition viewport_projection.hpp:74
Projects a visible musical-time range onto a horizontal pixel span.
Definition viewport_projection.hpp:36
PianoRollPitchRuler()
Creates a named vertical chromatic ruler ready for pitch projection.
void set_pitch_projection(const timeline_editor::PitchProjection &projection)
Aligns this ruler's frame and inclusive note range to a piano-roll projection while preserving its cu...
void set_host(timeline_editor::NoteEditIntentHost *host)
Where emitted intents go.
const std::vector< PianoRollRefusal > & refusals() const noexcept
Refusals recorded since the last clear_refusals(), in order.
Definition piano_roll_view.hpp:147
std::span< const timeline::NoteEvent > notes() const
The bound clip's notes, or empty when nothing is bound.
std::function< std::optional< timeline::NoteEvent >( timebase::TickPosition start, std::uint8_t pitch)> NoteFactory
Builds the payload for a create-note gesture at a lattice position.
Definition piano_roll_view.hpp:97
bool gesture_open() const noexcept
Whether a pointer gesture is mid-flight.
Definition piano_roll_view.hpp:152
void set_layout(const PianoRollLayout &layout)
void on_mouse_event(const view::MouseEvent &event) override
Erase lives here rather than on the button-less channel because it needs to know which button pressed...
void set_hit_metrics(const view::HitMetrics &metrics)
Pointer geometry, resolved once per gesture rather than per hit test.
void on_mouse_drag(view::Point position) override
void paint(canvas::Canvas &canvas) override
std::optional< view::Rect > note_rect(timeline::ItemId note_id) const
Rectangle a note occupies, in this view's local coordinates, or nullopt when the identity is not in t...
std::size_t visited_candidate_count() const noexcept
How many time-overlapping note candidates the last paint() examined.
Definition piano_roll_view.hpp:144
void on_mouse_up(view::Point position) override
void on_mouse_down(view::Point position) override
bool wants_mouse_input() const override
True if this widget handles mouse down/drag through virtual methods even when it does not expose JS p...
Definition piano_roll_view.hpp:157
void set_note_factory(NoteFactory factory)
Enables the create-note gesture.
void set_clip(const timeline::Project *project, timeline::ItemId sequence_id, timeline::ItemId track_id, timeline::ItemId clip_id)
Borrows the project to paint and hit-test, and names the MIDI clip whose notes this roll edits.
void clear_refusals()
Definition piano_roll_view.hpp:148
std::size_t painted_note_count() const noexcept
How many notes the last paint() actually drew.
Definition piano_roll_view.hpp:137
void set_continuous_gestures(bool enabled) noexcept
Opts into continuous transform phases.
Definition piano_roll_view.hpp:123
void on_mouse_cancel(view::Point position) override
Pointer / touch cancellation (iOS touchesCancelled, etc.).
Definition midi_keyboard.hpp:12
Definition view.hpp:73
Position position() const
Definition view.hpp:1767
const std::shared_ptr< WidgetMetrics > & metrics() const
Definition view.hpp:251
bool enabled() const
CSS :disabled equivalent — blocks input, reduces opacity.
Definition view.hpp:715
Pointer-neutral editing intents and their lowering to ordinary transactions.
GesturePhase
Lifecycle position of a transaction within an interactive gesture.
Definition command.hpp:79
NoteEditIntentKind
What a piano-roll gesture does to one note.
Definition edit_intent.hpp:85
SequencerUiHostT< ValidatedNoteEditIntent > NoteEditIntentHost
Host binding used by a piano-roll front-end before command lowering.
Definition edit_intent.hpp:145
@ Project
Definition model.hpp:945
PianoRollRefusal
Why the piano roll declined to emit an intent a gesture would otherwise have produced.
Definition piano_roll_view.hpp:62
@ InvalidNote
A note factory returned a note the note domain rejects, or the gesture would have produced one.
Definition piano_roll_view.hpp:65
@ OutsideClip
A move or resize would have left the note's own clip.
Definition piano_roll_view.hpp:69
Device-appropriate target sizing shared by pointer-driven hit tests.
Definition affine_transform.hpp:24
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
Definition arranger_view.hpp:17
@ kModNone
Definition input_events.hpp:16
@ mouse
Mouse cursor (default).
Definition input_events.hpp:76
Definition tick.hpp:56
Definition tick.hpp:61
Nonzero monotonic identity for a Timeline-owned object.
Definition item_id.hpp:19
A resolved note lattice, supplied by whoever owns the viewport.
Definition piano_roll_view.hpp:35
timeline_editor::TickProjection time
Definition piano_roll_view.hpp:36
timeline_editor::PitchProjection pitch
Definition piano_roll_view.hpp:37
timebase::TickDuration snap
Grid the authored start of an inserted or moved note lands on.
Definition piano_roll_view.hpp:40
Minimum hit-target sizing for one pointer type.
Definition hit_metrics.hpp:24
static constexpr HitMetrics for_pointer(PointerType type) noexcept
Metrics carrying this pointer type's default target extent.
Definition hit_metrics.hpp:43
Rich mouse/pointer event with position, modifiers, button state, pointer ID, and stylus properties.
Definition input_events.hpp:104
Definition geometry.hpp:20