mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
refactor code for region trimming from Pianoroll/MidiView
This splits out boundary-dragging things into boundary.{cc,h} and the rest
into CueEditor
This commit is contained in:
parent
cd9fe29347
commit
6187dd35c8
11 changed files with 250 additions and 190 deletions
116
gtk2_ardour/boundary.cc
Normal file
116
gtk2_ardour/boundary.cc
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Paul Davis <paul@linuxaudiosystems.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "boundary.h"
|
||||||
|
#include "ui_config.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
StartBoundaryRect::render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
|
{
|
||||||
|
Rectangle::render (area, context);
|
||||||
|
|
||||||
|
ArdourCanvas::Rect self (item_to_window (_rect));
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
|
||||||
|
context->arc (self.x1, (self.y0 + (self.height() / 2.)) - radius, radius, -(M_PI/2.), (M_PI/2.));
|
||||||
|
Gtkmm2ext::set_source_rgba (context, _outline_color);
|
||||||
|
context->fill ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
StartBoundaryRect::covers (ArdourCanvas::Duple const & point) const
|
||||||
|
{
|
||||||
|
ArdourCanvas::Rect self (item_to_window (_rect));
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
|
||||||
|
if ((point.x >= self.x1 - (20. * scale)) && (point.x < self.x1)) {
|
||||||
|
/* within 20 (scaled) pixels of the boundary, on the right */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Approximate the semicircle handle with a square */
|
||||||
|
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
double cy = self.y0 + (self.height() / 2.);
|
||||||
|
|
||||||
|
if (point.x >= self.x1 && point.x < self.x1 + radius &&
|
||||||
|
point.y >= cy - radius && point.y < cy + radius) {
|
||||||
|
/*inside rectangle that approximates the handle */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
StartBoundaryRect::compute_bounding_box() const
|
||||||
|
{
|
||||||
|
Rectangle::compute_bounding_box ();
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
_bounding_box = _bounding_box.expand (0., radius + _outline_width + 1.0, 0., 0.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EndBoundaryRect::render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
|
{
|
||||||
|
Rectangle::render (area, context);
|
||||||
|
|
||||||
|
ArdourCanvas::Rect self (item_to_window (_rect));
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
|
||||||
|
context->arc (self.x0, (self.y0 + (self.height() / 2.)) - radius, radius, (M_PI/2.), -(M_PI/2.));
|
||||||
|
Gtkmm2ext::set_source_rgba (context, _outline_color);
|
||||||
|
context->fill ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
EndBoundaryRect::covers (ArdourCanvas::Duple const & point) const
|
||||||
|
{
|
||||||
|
ArdourCanvas::Rect self (item_to_window (_rect));
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
|
||||||
|
if ((point.x >= self.x0) && (point.x < self.x0 + (20. * scale))) {
|
||||||
|
/* within 20 (scaled) pixels of the left edge */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Approximate the semicircle handle with a square */
|
||||||
|
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
double cy = self.y0 + (self.height() / 2.);
|
||||||
|
|
||||||
|
if (point.x <= self.x0 && point.x >= self.x0 - radius && point.y >= cy - radius && point.y < cy + radius) {
|
||||||
|
/* within a rectangle approximating the handle */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EndBoundaryRect::compute_bounding_box() const
|
||||||
|
{
|
||||||
|
Rectangle::compute_bounding_box ();
|
||||||
|
const double scale = UIConfiguration::instance().get_ui_scale();
|
||||||
|
const double radius = 10. * scale;
|
||||||
|
_bounding_box = _bounding_box.expand (0., 0., 0., radius + _outline_width);
|
||||||
|
}
|
||||||
42
gtk2_ardour/boundary.h
Normal file
42
gtk2_ardour/boundary.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Paul Davis <paul@linuxaudiosystems.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "canvas/rectangle.h"
|
||||||
|
|
||||||
|
class StartBoundaryRect : public ArdourCanvas::Rectangle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StartBoundaryRect (ArdourCanvas::Item* p) : ArdourCanvas::Rectangle (p) {}
|
||||||
|
|
||||||
|
void render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
||||||
|
bool covers (ArdourCanvas::Duple const& point) const;
|
||||||
|
void compute_bounding_box () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EndBoundaryRect : public ArdourCanvas::Rectangle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EndBoundaryRect (ArdourCanvas::Item* p) : ArdourCanvas::Rectangle (p) {}
|
||||||
|
|
||||||
|
void render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
||||||
|
bool covers (ArdourCanvas::Duple const& point) const;
|
||||||
|
void compute_bounding_box () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -1885,3 +1885,35 @@ CueEditor::metric_get_bbt (std::vector<ArdourCanvas::Ruler::Mark>& marks, sample
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CueEditor::set_start (Temporal::timepos_t const & p)
|
||||||
|
{
|
||||||
|
EC_LOCAL_TEMPO_SCOPE;
|
||||||
|
|
||||||
|
if (ref.trigger()) {
|
||||||
|
ref.trigger()->the_region()->trim_front (p);
|
||||||
|
} else if (_region) {
|
||||||
|
begin_reversible_command (_("trim region front"));
|
||||||
|
_region->clear_changes ();
|
||||||
|
_region->trim_front (_region->source_position() + p);
|
||||||
|
add_command (new PBD::StatefulDiffCommand (_region));
|
||||||
|
commit_reversible_command ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CueEditor::set_end (Temporal::timepos_t const & p)
|
||||||
|
{
|
||||||
|
EC_LOCAL_TEMPO_SCOPE;
|
||||||
|
|
||||||
|
if (ref.trigger()) {
|
||||||
|
ref.trigger()->the_region()->trim_end (p);
|
||||||
|
} else if (_region) {
|
||||||
|
begin_reversible_command (_("trim region end"));
|
||||||
|
_region->clear_changes ();
|
||||||
|
_region->trim_end (_region->source_position() + p);
|
||||||
|
add_command (new PBD::StatefulDiffCommand (_region));
|
||||||
|
commit_reversible_command ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,11 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
|
||||||
int set_state (const XMLNode&, int version);
|
int set_state (const XMLNode&, int version);
|
||||||
XMLNode& get_state () const;
|
XMLNode& get_state () const;
|
||||||
|
|
||||||
|
void set_start (Temporal::timepos_t const & p);
|
||||||
|
void set_end (Temporal::timepos_t const & p);
|
||||||
|
virtual void shift_contents (Temporal::timepos_t const &, bool model_too) {}
|
||||||
|
virtual Temporal::timepos_t source_to_timeline (Temporal::timepos_t const & source_pos) const { return source_pos; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ArdourCanvas::GtkCanvasViewport _canvas_viewport;
|
ArdourCanvas::GtkCanvasViewport _canvas_viewport;
|
||||||
ArdourCanvas::GtkCanvas& _canvas;
|
ArdourCanvas::GtkCanvas& _canvas;
|
||||||
|
|
@ -263,4 +268,3 @@ class CueEditor : public EditingContext, public PBD::HistoryOwner
|
||||||
bool hscroll_press (GdkEventButton*);
|
bool hscroll_press (GdkEventButton*);
|
||||||
bool hscroll_release (GdkEventButton*);
|
bool hscroll_release (GdkEventButton*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@
|
||||||
#include "automation_time_axis.h"
|
#include "automation_time_axis.h"
|
||||||
#include "bbt_marker_dialog.h"
|
#include "bbt_marker_dialog.h"
|
||||||
#include "control_point.h"
|
#include "control_point.h"
|
||||||
|
#include "cue_editor.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "editor_cursors.h"
|
#include "editor_cursors.h"
|
||||||
|
|
@ -6890,6 +6891,7 @@ NoteCreateDrag::finished (GdkEvent* ev, bool had_movement)
|
||||||
if (UIConfiguration::instance().get_select_last_drawn_note_only()) {
|
if (UIConfiguration::instance().get_select_last_drawn_note_only()) {
|
||||||
_midi_view->clear_note_selection ();
|
_midi_view->clear_note_selection ();
|
||||||
}
|
}
|
||||||
|
|
||||||
_midi_view->create_note_at (timepos_t (start), _drag_rect->y0 (), length, ev->button.state, false);
|
_midi_view->create_note_at (timepos_t (start), _drag_rect->y0 (), length, ev->button.state, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7570,12 +7572,13 @@ VelocityLineDrag::aborted (bool)
|
||||||
vd->end_line_drag (false);
|
vd->end_line_drag (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipStartDrag::ClipStartDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, Pianoroll& m)
|
ClipStartDrag::ClipStartDrag (CueEditor& cedit, ArdourCanvas::Rectangle& r)
|
||||||
: Drag (ec, &r, Temporal::BeatTime, nullptr, false)
|
: Drag (cedit, &r, Temporal::BeatTime, nullptr, false)
|
||||||
, mce (m)
|
, ce (cedit)
|
||||||
, dragging_rect (&r)
|
, dragging_rect (&r)
|
||||||
, original_rect (r.get())
|
, original_rect (r.get())
|
||||||
{
|
{
|
||||||
|
DEBUG_TRACE (DEBUG::Drags, "start ClipStartDrag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipStartDrag::~ClipStartDrag ()
|
ClipStartDrag::~ClipStartDrag ()
|
||||||
|
|
@ -7603,15 +7606,15 @@ ClipStartDrag::motion (GdkEvent* event, bool first_move)
|
||||||
double x, y;
|
double x, y;
|
||||||
gdk_event_get_coords (event, &x, &y);
|
gdk_event_get_coords (event, &x, &y);
|
||||||
|
|
||||||
if (x >= editing_context.timeline_origin()) {
|
if (x >= ce.timeline_origin()) {
|
||||||
|
|
||||||
/* Compute snapped position and adjust rect item if appropriate */
|
/* Compute snapped position and adjust rect item if appropriate */
|
||||||
|
|
||||||
timepos_t pos = adjusted_current_time (event);
|
timepos_t pos = adjusted_current_time (event);
|
||||||
editing_context.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
ce.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
||||||
double pix = editing_context.timeline_to_canvas (editing_context.time_to_pixel (pos));
|
double pix = ce.timeline_to_canvas (ce.time_to_pixel (pos));
|
||||||
|
|
||||||
if (pix >= editing_context.timeline_origin()) {
|
if (pix >= ce.timeline_origin()) {
|
||||||
r.x1 = dragging_rect->parent()->canvas_to_item (Duple (pix, 0.0)).x;
|
r.x1 = dragging_rect->parent()->canvas_to_item (Duple (pix, 0.0)).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7621,10 +7624,10 @@ ClipStartDrag::motion (GdkEvent* event, bool first_move)
|
||||||
* coordinates are clamped to zero (no negative values).
|
* coordinates are clamped to zero (no negative values).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
x -= editing_context.timeline_origin();
|
x -= ce.timeline_origin();
|
||||||
timepos_t tp (mce.pixel_to_sample (x));
|
timepos_t tp (ce.pixel_to_sample (x));
|
||||||
Beats b (tp.beats() * -1);
|
Beats b (tp.beats() * -1);
|
||||||
mce.shift_midi (timepos_t (b), false);
|
ce.shift_contents (timepos_t (b), false);
|
||||||
|
|
||||||
/* ensure the line is in the right place */
|
/* ensure the line is in the right place */
|
||||||
|
|
||||||
|
|
@ -7645,22 +7648,17 @@ ClipStartDrag::finished (GdkEvent* event, bool movement_occured)
|
||||||
double x, y;
|
double x, y;
|
||||||
gdk_event_get_coords (event, &x, &y);
|
gdk_event_get_coords (event, &x, &y);
|
||||||
|
|
||||||
if (x >= editing_context.timeline_origin()) {
|
if (x >= ce.timeline_origin()) {
|
||||||
|
|
||||||
timepos_t pos = adjusted_current_time (event);
|
timepos_t pos = adjusted_current_time (event);
|
||||||
editing_context.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
ce.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
||||||
double pix = editing_context.timeline_to_canvas (editing_context.time_to_pixel (pos));
|
double pix = ce.timeline_to_canvas (ce.time_to_pixel (pos));
|
||||||
|
|
||||||
if (pix >= editing_context.timeline_origin()) {
|
if (pix >= ce.timeline_origin()) {
|
||||||
|
|
||||||
assert (mce.midi_view());
|
pos = ce.source_to_timeline (pos);
|
||||||
|
ce.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
||||||
if (mce.midi_view()->show_source()) {
|
ce.set_start (pos);
|
||||||
pos = mce.midi_view()->source_beats_to_timeline (pos.beats());
|
|
||||||
}
|
|
||||||
|
|
||||||
editing_context.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
|
||||||
mce.set_trigger_start (pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -7669,10 +7667,10 @@ ClipStartDrag::finished (GdkEvent* event, bool movement_occured)
|
||||||
* coordinates are clamped to zero (no negative values).
|
* coordinates are clamped to zero (no negative values).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
x -= editing_context.timeline_origin();
|
x -= ce.timeline_origin();
|
||||||
timepos_t tp (mce.pixel_to_sample (x));
|
timepos_t tp (ce.pixel_to_sample (x));
|
||||||
Beats b (tp.beats() * -1);
|
Beats b (tp.beats() * -1);
|
||||||
mce.shift_midi (timepos_t (b), true);
|
ce.shift_contents (timepos_t (b), true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7684,16 +7682,17 @@ ClipStartDrag::aborted (bool movement_occured)
|
||||||
|
|
||||||
if (movement_occured) {
|
if (movement_occured) {
|
||||||
/* redraw to get notes back to the right places */
|
/* redraw to get notes back to the right places */
|
||||||
mce.shift_midi (timepos_t (Temporal::Beats()), false);
|
ce.shift_contents (timepos_t (Temporal::Beats()), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipEndDrag::ClipEndDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, Pianoroll& m)
|
ClipEndDrag::ClipEndDrag (CueEditor& cedit, ArdourCanvas::Rectangle& r)
|
||||||
: Drag (ec, &r, Temporal::BeatTime, nullptr, false)
|
: Drag (cedit, &r, Temporal::BeatTime, nullptr, false)
|
||||||
, mce (m)
|
, ce (cedit)
|
||||||
, dragging_rect (&r)
|
, dragging_rect (&r)
|
||||||
, original_rect (r.get())
|
, original_rect (r.get())
|
||||||
{
|
{
|
||||||
|
DEBUG_TRACE (DEBUG::Drags, "start ClipEndDrag\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipEndDrag::~ClipEndDrag ()
|
ClipEndDrag::~ClipEndDrag ()
|
||||||
|
|
@ -7719,10 +7718,10 @@ ClipEndDrag::motion (GdkEvent* event, bool)
|
||||||
ArdourCanvas::Rect r (original_rect);
|
ArdourCanvas::Rect r (original_rect);
|
||||||
|
|
||||||
timepos_t pos (adjusted_current_time (event));
|
timepos_t pos (adjusted_current_time (event));
|
||||||
editing_context.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
ce.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
||||||
double pix = editing_context.timeline_to_canvas (editing_context.time_to_pixel (pos));
|
double pix = ce.timeline_to_canvas (ce.time_to_pixel (pos));
|
||||||
|
|
||||||
if (pix > editing_context.timeline_origin()) {
|
if (pix > ce.timeline_origin()) {
|
||||||
r.x0 = dragging_rect->parent()->canvas_to_item (Duple (pix, 0.0)).x;
|
r.x0 = dragging_rect->parent()->canvas_to_item (Duple (pix, 0.0)).x;
|
||||||
} else {
|
} else {
|
||||||
r.x0 = r.x1 - 1.;
|
r.x0 = r.x1 - 1.;
|
||||||
|
|
@ -7740,8 +7739,8 @@ ClipEndDrag::finished (GdkEvent* event, bool movement_occured)
|
||||||
}
|
}
|
||||||
|
|
||||||
timepos_t pos = adjusted_current_time (event);
|
timepos_t pos = adjusted_current_time (event);
|
||||||
editing_context.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
ce.snap_to_with_modifier (pos, event, Temporal::RoundNearest, ARDOUR::SnapToGrid_Scaled, true);
|
||||||
mce.set_trigger_end (pos);
|
ce.set_end (pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ namespace PBD {
|
||||||
class StatefulDiffCommand;
|
class StatefulDiffCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CueEditor;
|
||||||
class PatchChange;
|
class PatchChange;
|
||||||
class EditingContext;
|
class EditingContext;
|
||||||
class Editor;
|
class Editor;
|
||||||
|
|
@ -1615,7 +1616,7 @@ class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoi
|
||||||
class ClipStartDrag : public Drag
|
class ClipStartDrag : public Drag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClipStartDrag (EditingContext&, ArdourCanvas::Rectangle &, Pianoroll& m);
|
ClipStartDrag (CueEditor&, ArdourCanvas::Rectangle &);
|
||||||
~ClipStartDrag ();
|
~ClipStartDrag ();
|
||||||
|
|
||||||
void start_grab (GdkEvent*,Gdk::Cursor*);
|
void start_grab (GdkEvent*,Gdk::Cursor*);
|
||||||
|
|
@ -1625,7 +1626,7 @@ class ClipStartDrag : public Drag
|
||||||
void aborted (bool);
|
void aborted (bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pianoroll& mce;
|
CueEditor& ce;
|
||||||
ArdourCanvas::Rectangle* dragging_rect;
|
ArdourCanvas::Rectangle* dragging_rect;
|
||||||
ArdourCanvas::Rect original_rect;
|
ArdourCanvas::Rect original_rect;
|
||||||
};
|
};
|
||||||
|
|
@ -1633,7 +1634,7 @@ class ClipStartDrag : public Drag
|
||||||
class ClipEndDrag : public Drag
|
class ClipEndDrag : public Drag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClipEndDrag (EditingContext&, ArdourCanvas::Rectangle &, Pianoroll& m);
|
ClipEndDrag (CueEditor&, ArdourCanvas::Rectangle &);
|
||||||
~ClipEndDrag ();
|
~ClipEndDrag ();
|
||||||
|
|
||||||
void start_grab (GdkEvent*,Gdk::Cursor*);
|
void start_grab (GdkEvent*,Gdk::Cursor*);
|
||||||
|
|
@ -1643,7 +1644,7 @@ class ClipEndDrag : public Drag
|
||||||
void aborted (bool);
|
void aborted (bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pianoroll& mce;
|
CueEditor& ce;
|
||||||
ArdourCanvas::Rectangle* dragging_rect;
|
ArdourCanvas::Rectangle* dragging_rect;
|
||||||
ArdourCanvas::Rect original_rect;
|
ArdourCanvas::Rect original_rect;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5364,98 +5364,3 @@ MidiView::set_visible_channel (int chn, bool clear_selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
StartBoundaryRect::render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|
||||||
{
|
|
||||||
Rectangle::render (area, context);
|
|
||||||
|
|
||||||
ArdourCanvas::Rect self (item_to_window (_rect));
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
|
|
||||||
context->arc (self.x1, (self.y0 + (self.height() / 2.)) - radius, radius, -(M_PI/2.), (M_PI/2.));
|
|
||||||
Gtkmm2ext::set_source_rgba (context, _outline_color);
|
|
||||||
context->fill ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
StartBoundaryRect::covers (ArdourCanvas::Duple const & point) const
|
|
||||||
{
|
|
||||||
ArdourCanvas::Rect self (item_to_window (_rect));
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
|
|
||||||
if ((point.x >= self.x1 - (20. * scale)) && (point.x < self.x1)) {
|
|
||||||
/* within 20 (scaled) pixels of the boundary, on the right */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Approximate the semicircle handle with a square */
|
|
||||||
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
double cy = self.y0 + (self.height() / 2.);
|
|
||||||
|
|
||||||
if (point.x >= self.x1 && point.x < self.x1 + radius &&
|
|
||||||
point.y >= cy - radius && point.y < cy + radius) {
|
|
||||||
/*inside rectangle that approximates the handle */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StartBoundaryRect::compute_bounding_box() const
|
|
||||||
{
|
|
||||||
Rectangle::compute_bounding_box ();
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
_bounding_box = _bounding_box.expand (0., radius + _outline_width + 1.0, 0., 0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EndBoundaryRect::render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|
||||||
{
|
|
||||||
Rectangle::render (area, context);
|
|
||||||
|
|
||||||
ArdourCanvas::Rect self (item_to_window (_rect));
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
|
|
||||||
context->arc (self.x0, (self.y0 + (self.height() / 2.)) - radius, radius, (M_PI/2.), -(M_PI/2.));
|
|
||||||
Gtkmm2ext::set_source_rgba (context, _outline_color);
|
|
||||||
context->fill ();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
EndBoundaryRect::covers (ArdourCanvas::Duple const & point) const
|
|
||||||
{
|
|
||||||
ArdourCanvas::Rect self (item_to_window (_rect));
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
|
|
||||||
if ((point.x >= self.x0) && (point.x < self.x0 + (20. * scale))) {
|
|
||||||
/* within 20 (scaled) pixels of the left edge */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Approximate the semicircle handle with a square */
|
|
||||||
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
double cy = self.y0 + (self.height() / 2.);
|
|
||||||
|
|
||||||
if (point.x <= self.x0 && point.x >= self.x0 - radius && point.y >= cy - radius && point.y < cy + radius) {
|
|
||||||
/* within a rectangle approximating the handle */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EndBoundaryRect::compute_bounding_box() const
|
|
||||||
{
|
|
||||||
Rectangle::compute_bounding_box ();
|
|
||||||
const double scale = UIConfiguration::instance().get_ui_scale();
|
|
||||||
const double radius = 10. * scale;
|
|
||||||
_bounding_box = _bounding_box.expand (0., 0., 0., radius + _outline_width);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "canvas/rectangle.h"
|
#include "canvas/rectangle.h"
|
||||||
|
|
||||||
|
#include "boundary.h"
|
||||||
#include "editing.h"
|
#include "editing.h"
|
||||||
#include "region_view.h"
|
#include "region_view.h"
|
||||||
#include "midi_view_background.h"
|
#include "midi_view_background.h"
|
||||||
|
|
@ -79,26 +80,6 @@ class EditingContext;
|
||||||
class PasteContext;
|
class PasteContext;
|
||||||
class Drag;
|
class Drag;
|
||||||
|
|
||||||
class StartBoundaryRect : public ArdourCanvas::Rectangle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StartBoundaryRect (ArdourCanvas::Item* p) : ArdourCanvas::Rectangle (p) {}
|
|
||||||
|
|
||||||
void render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
|
||||||
bool covers (ArdourCanvas::Duple const& point) const;
|
|
||||||
void compute_bounding_box () const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EndBoundaryRect : public ArdourCanvas::Rectangle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EndBoundaryRect (ArdourCanvas::Item* p) : ArdourCanvas::Rectangle (p) {}
|
|
||||||
|
|
||||||
void render (ArdourCanvas::Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
|
||||||
bool covers (ArdourCanvas::Duple const& point) const;
|
|
||||||
void compute_bounding_box () const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MidiView : public virtual sigc::trackable, public LineMerger
|
class MidiView : public virtual sigc::trackable, public LineMerger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -784,38 +784,6 @@ Pianoroll::canvas_cue_end_event (GdkEvent* event, ArdourCanvas::Item* item)
|
||||||
return typed_event (item, event, ClipEndItem);
|
return typed_event (item, event, ClipEndItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Pianoroll::set_trigger_start (Temporal::timepos_t const & p)
|
|
||||||
{
|
|
||||||
EC_LOCAL_TEMPO_SCOPE;
|
|
||||||
|
|
||||||
if (ref.trigger()) {
|
|
||||||
ref.trigger()->the_region()->trim_front (p);
|
|
||||||
} else {
|
|
||||||
begin_reversible_command (_("trim region front"));
|
|
||||||
view->midi_region()->clear_changes ();
|
|
||||||
view->midi_region()->trim_front (view->midi_region()->source_position() + p);
|
|
||||||
add_command (new StatefulDiffCommand (view->midi_region()));
|
|
||||||
commit_reversible_command ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Pianoroll::set_trigger_end (Temporal::timepos_t const & p)
|
|
||||||
{
|
|
||||||
EC_LOCAL_TEMPO_SCOPE;
|
|
||||||
|
|
||||||
if (ref.trigger()) {
|
|
||||||
ref.trigger()->the_region()->trim_end (p);
|
|
||||||
} else {
|
|
||||||
begin_reversible_command (_("trim region end"));
|
|
||||||
view->midi_region()->clear_changes ();
|
|
||||||
view->midi_region()->trim_end (view->midi_region()->source_position() + p);
|
|
||||||
add_command (new StatefulDiffCommand (view->midi_region()));
|
|
||||||
commit_reversible_command ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Gtk::Widget&
|
Gtk::Widget&
|
||||||
Pianoroll::contents ()
|
Pianoroll::contents ()
|
||||||
{
|
{
|
||||||
|
|
@ -954,7 +922,7 @@ Pianoroll::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, It
|
||||||
case ClipStartItem: {
|
case ClipStartItem: {
|
||||||
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (item);
|
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (item);
|
||||||
if (r) {
|
if (r) {
|
||||||
_drags->set (new ClipStartDrag (*this, *r, *this), event);
|
_drags->set (new ClipStartDrag (*this, *r), event);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -963,7 +931,7 @@ Pianoroll::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, It
|
||||||
case ClipEndItem: {
|
case ClipEndItem: {
|
||||||
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (item);
|
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (item);
|
||||||
if (r) {
|
if (r) {
|
||||||
_drags->set (new ClipEndDrag (*this, *r, *this), event);
|
_drags->set (new ClipEndDrag (*this, *r), event);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1937,7 +1905,7 @@ Pianoroll::allow_trim_cursors () const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Pianoroll::shift_midi (timepos_t const & t, bool model)
|
Pianoroll::shift_contents (timepos_t const & t, bool model)
|
||||||
{
|
{
|
||||||
EC_LOCAL_TEMPO_SCOPE;
|
EC_LOCAL_TEMPO_SCOPE;
|
||||||
|
|
||||||
|
|
@ -2117,4 +2085,14 @@ Pianoroll::parameter_changed (std::string param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timepos_t
|
||||||
|
Pianoroll::source_to_timeline (timepos_t const & source_pos) const
|
||||||
|
{
|
||||||
|
assert (midi_view());
|
||||||
|
|
||||||
|
if (midi_view()->show_source()) {
|
||||||
|
return midi_view()->source_beats_to_timeline (source_pos.beats());
|
||||||
|
}
|
||||||
|
|
||||||
|
return source_pos;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,12 +118,13 @@ class Pianoroll : public CueEditor
|
||||||
void set_session (ARDOUR::Session*);
|
void set_session (ARDOUR::Session*);
|
||||||
bool allow_trim_cursors () const;
|
bool allow_trim_cursors () const;
|
||||||
|
|
||||||
void shift_midi (Temporal::timepos_t const &, bool model);
|
void shift_contents (Temporal::timepos_t const &, bool model);
|
||||||
void make_a_region();
|
void make_a_region();
|
||||||
|
|
||||||
ARDOUR::InstrumentInfo* instrument_info() const;
|
ARDOUR::InstrumentInfo* instrument_info() const;
|
||||||
|
|
||||||
void set_show_source (bool);
|
void set_show_source (bool);
|
||||||
|
Temporal::timepos_t source_to_timeline (Temporal::timepos_t const & source_pos) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
|
Temporal::timepos_t snap_to_grid (Temporal::timepos_t const & start,
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ gtk2_ardour_sources = [
|
||||||
'bbt_marker_dialog.cc',
|
'bbt_marker_dialog.cc',
|
||||||
'big_clock_window.cc',
|
'big_clock_window.cc',
|
||||||
'big_transport_window.cc',
|
'big_transport_window.cc',
|
||||||
|
'boundary.cc',
|
||||||
'bundle_manager.cc',
|
'bundle_manager.cc',
|
||||||
'clock_group.cc',
|
'clock_group.cc',
|
||||||
'color_theme_manager.cc',
|
'color_theme_manager.cc',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue