Indicate arrangement section selection on canvas

This commit is contained in:
Ben Loftis 2023-09-07 21:20:05 +02:00 committed by Robin Gareus
parent b243b93072
commit e81b2353cc
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
8 changed files with 206 additions and 8 deletions

View File

@ -122,6 +122,7 @@
#include "editor_regions.h"
#include "editor_route_groups.h"
#include "editor_routes.h"
#include "editor_section_box.h"
#include "editor_sections.h"
#include "editor_snapshots.h"
#include "editor_sources.h"
@ -410,6 +411,7 @@ Editor::Editor ()
, _last_region_menu_was_main (false)
, _track_selection_change_without_scroll (false)
, _editor_track_selection_change_without_scroll (false)
, _section_box (0)
, _playhead_cursor (0)
, _snapped_cursor (0)
, cd_marker_bar_drag_rect (0)
@ -924,6 +926,7 @@ Editor::~Editor()
delete selection;
delete cut_buffer;
delete _cursors;
delete _section_box;
LuaInstance::destroy_instance ();
@ -1110,6 +1113,7 @@ Editor::control_scroll (float fraction)
/* move visuals, we'll catch up with it later */
_playhead_cursor->set_position (*_control_scroll_target);
update_section_box ();
UpdateAllTransportClocks (*_control_scroll_target);
if (*_control_scroll_target > (current_page_samples() / 2)) {
@ -1265,6 +1269,8 @@ Editor::map_position_change (samplepos_t sample)
if (!_session->locate_initiated()) {
_playhead_cursor->set_position (sample);
}
update_section_box ();
}
void
@ -1584,6 +1590,41 @@ Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::It
xfade_out_context_menu.popup (button, time);
}
void
Editor::popup_section_box_menu (int button, int32_t time)
{
using namespace Menu_Helpers;
section_box_menu.set_name ("ArdourContextMenu");
MenuList& items (section_box_menu.items());
items.clear ();
items.push_back (MenuElem (_("Copy/Paste Range Section to Edit Point"), sigc::bind (sigc::mem_fun (*this, &Editor::cut_copy_section), CopyPasteSection)));
items.push_back (MenuElem (_("Cut/Paste Range Section to Edit Point"), sigc::bind (sigc::mem_fun (*this, &Editor::cut_copy_section), CutPasteSection)));
items.push_back (MenuElem (_("Delete Range Section"), sigc::bind (sigc::mem_fun (*this, &Editor::cut_copy_section), DeleteSection)));
#if 0
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Delete all markers in Section"), sigc::bind (sigc::mem_fun (*this, &Editor::cut_copy_section), DeleteSection)));
#endif
timepos_t start, end;
if (get_selection_extents (start, end)) {
/* add some items from build_marker_menu () */
Location* l = _session->locations ()->mark_at (start);
assert (l);
LocationMarkers* lm = find_location_markers (l);
assert (lm && lm->start);
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Move Playhead to Marker"), sigc::bind (sigc::mem_fun(*_session, &Session::request_locate), start.samples (), false, MustStop, TRS_UI)));
items.push_back (MenuElem (_("Rename..."), sigc::bind (sigc::mem_fun(*this, &Editor::rename_marker), lm->start)));
}
items.push_back (SeparatorElem());
add_selection_context_items (items, true);
section_box_menu.popup (button, time);
}
void
Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
{
@ -2481,6 +2522,7 @@ Editor::set_state (const XMLNode& node, int version)
}
update_selection_markers ();
update_section_box ();
node.get_property ("mixer-width", editor_mixer_strip_width);
@ -5019,6 +5061,7 @@ Editor::on_samples_per_pixel_changed ()
refresh_location_display();
_summary->set_overlays_dirty ();
update_section_box ();
update_marker_labels ();
instant_save ();
@ -5703,6 +5746,7 @@ Editor::located ()
if (_follow_playhead && !_pending_initial_locate) {
reset_x_origin_to_follow_playhead ();
}
update_section_box ();
}
_pending_locate_request = false;
@ -6472,6 +6516,8 @@ Editor::super_rapid_screen_update ()
_playhead_cursor->set_position (sample);
}
update_section_box ();
if (_session->requested_return_sample() >= 0) {
_last_update_time = 0;
return;

View File

@ -145,6 +145,7 @@ class QuantizeDialog;
class RegionPeakCursor;
class RhythmFerret;
class RulerDialog;
class SectionBox;
class Selection;
class SelectionPropertiesBox;
class SoundFileOmega;
@ -733,6 +734,7 @@ private:
void toggle_marker_lines ();
void set_marker_line_visibility (bool);
void update_selection_markers ();
void update_section_box ();
void jump_forward_to_mark ();
void jump_backward_to_mark ();
@ -852,12 +854,14 @@ private:
void collect_new_region_view (RegionView*);
void collect_and_select_new_region_view (RegionView*);
Gtk::Menu section_box_menu;
Gtk::Menu track_context_menu;
Gtk::Menu track_region_context_menu;
Gtk::Menu track_selection_context_menu;
GdkEvent context_click_event;
void popup_section_box_menu (int, int);
void popup_track_context_menu (int, int, ItemType, bool);
Gtk::Menu* build_track_context_menu ();
Gtk::Menu* build_track_bus_context_menu ();
@ -1795,6 +1799,7 @@ private:
/* non-public event handlers */
bool canvas_section_box_event (GdkEvent* event);
bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*);
bool track_canvas_scroll (GdkEventScroll* event);
@ -2099,6 +2104,8 @@ private:
bool audio_region_selection_covers (samplepos_t where);
SectionBox* _section_box;
/* playhead and edit cursor */
EditorCursor* _playhead_cursor;

View File

@ -53,6 +53,7 @@
#include "editor_drag.h"
#include "region_view.h"
#include "editor_group_tabs.h"
#include "editor_section_box.h"
#include "editor_summary.h"
#include "video_timeline.h"
#include "keyboard.h"
@ -143,13 +144,6 @@ Editor::initialize_canvas ()
_time_markers_group = new ArdourCanvas::Container (h_scroll_group);
CANVAS_DEBUG_NAME (_time_markers_group, "time bars");
/* group above rulers, to show selection triangles */
_selection_marker_group = new ArdourCanvas::Container (h_scroll_group);
CANVAS_DEBUG_NAME (_selection_marker_group, "Canvas Selection Ruler");
_selection_marker->start = new SelectionMarker (*this, *_selection_marker_group, "play head", ArdourMarker::SelectionStart);
_selection_marker->end = new SelectionMarker (*this, *_selection_marker_group, "play head", ArdourMarker::SelectionEnd);
_selection_marker_group->raise_to_top ();
/* Note that because of ascending-y-axis coordinates, this order is
* bottom-to-top. But further note that the actual order is set in
* ::update_ruler_visibility()
@ -279,6 +273,17 @@ Editor::initialize_canvas ()
_canvas_grid_zone->Event.connect (sigc::mem_fun (*this, &Editor::canvas_grid_zone_event));
_canvas_grid_zone->set_ignore_events (true);
/* and now the timeline-selection rectangle which is controlled by the markers */
_section_box = new SectionBox (*this, cursor_scroll_group);
_section_box->Event.connect (sigc::mem_fun (*this, &Editor::canvas_section_box_event));
/* group above rulers, to show selection triangles */
_selection_marker_group = new ArdourCanvas::Container (cursor_scroll_group);
CANVAS_DEBUG_NAME (_selection_marker_group, "Canvas Selection Ruler");
_selection_marker->start = new SelectionMarker (*this, *_selection_marker_group, "selection", ArdourMarker::SelectionStart);
_selection_marker->end = new SelectionMarker (*this, *_selection_marker_group, "selection", ArdourMarker::SelectionEnd);
_selection_marker_group->raise_to_top ();
/* these signals will initially be delivered to the canvas itself, but if they end up remaining unhandled,
* they are passed to Editor-level handlers.
*/
@ -1063,6 +1068,9 @@ Editor::color_handler()
bbt_ruler->set_fill_color (base);
bbt_ruler->set_outline_color (text);
_section_box->set_fill_color (UIConfiguration::instance().color_mod ("selection", "selection rect"));
_section_box->set_outline_color (UIConfiguration::instance().color ("selection"));
_playhead_cursor->set_color (UIConfiguration::instance().color ("play head"));
meter_bar->set_fill_color (UIConfiguration::instance().color_mod ("meter bar", "marker bar"));

View File

@ -1188,7 +1188,7 @@ Editor::section_rect_event (GdkEvent* ev, Location* loc, ArdourCanvas::Rectangle
break;
}
/* and show section context menu */
//popup_section_box_menu (ev->button.button, ev->button.time);
popup_section_box_menu (ev->button.button, ev->button.time);
return true;
}
break;
@ -1204,6 +1204,32 @@ Editor::canvas_playhead_cursor_event (GdkEvent *event, ArdourCanvas::Item* item)
return typed_event (item, event, PlayheadCursorItem);
}
bool
Editor::canvas_section_box_event (GdkEvent *event)
{
switch (event->type) {
case GDK_BUTTON_PRESS:
if (!Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)
&& event->button.button == 1) {
_drags->set (new CursorDrag (this, *_playhead_cursor, false), event);
}
/*fallthrough*/
case GDK_2BUTTON_PRESS:
/*fallthrough*/
case GDK_3BUTTON_PRESS:
return !Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
case GDK_BUTTON_RELEASE:
if (Keyboard::is_context_menu_event (&event->button)) {
popup_section_box_menu (event->button.button, event->button.time);
return true;
}
return false;
default:
break;
}
return false;
}
bool
Editor::canvas_note_event (GdkEvent *event, ArdourCanvas::Item* item)
{

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 Robin Gareus <robin@gareus.org>
* Copyright (C) 2023 Ben Loftis <ben@harrisonaudio.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 <cmath>
#include "editor.h"
#include "editor_section_box.h"
using namespace ARDOUR;
SectionBox::SectionBox (Editor& ed, ArdourCanvas::Item* parent)
: ArdourCanvas::Rectangle (parent)
, _editor (ed)
{
set (ArdourCanvas::Rect (0, 0, 0, ArdourCanvas::COORD_MAX));
set_ignore_events (false);
set_outline_what (ArdourCanvas::Rectangle::What (Rectangle::LEFT | Rectangle::RIGHT));
set_outline (true);
set_fill (true);
hide ();
}
void
SectionBox::set_position (samplepos_t sample_start, samplepos_t sample_end)
{
double const new_start = _editor.sample_to_pixel_unrounded (sample_start);
double const new_end = _editor.sample_to_pixel_unrounded (sample_end);
if (rint (new_start) != rint (x0())) {
set_x0 (new_start + 0.5); // accommodate the 1/2 pixel "line" offset in cairo
}
if (rint (new_end) != rint (x1())) {
set_x1 (new_end + 0.5); // accommodate the 1/2 pixel "line" offset in cairo
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 Robin Gareus <robin@gareus.org>
* Copyright (C) 2023 Ben Loftis <ben@harrisonaudio.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.
*/
#ifndef __gtk_ardour_section_box_h__
#define __gtk_ardour_section_box_h__
#include "ardour/types.h"
#include "canvas/rectangle.h"
#include "canvas/types.h"
class Editor;
class SectionBox : public ArdourCanvas::Rectangle
{
public:
SectionBox (Editor&, ArdourCanvas::Item*);
void set_position (samplepos_t, samplepos_t);
private:
Editor& _editor;
};
#endif // __gtk_ardour_editor_cursors_h__

View File

@ -39,6 +39,7 @@
#include "editor.h"
#include "editor_drag.h"
#include "editor_routes.h"
#include "editor_section_box.h"
#include "editor_sources.h"
#include "actions.h"
#include "audio_time_axis.h"
@ -1264,6 +1265,17 @@ Editor::presentation_info_changed (PropertyChange const & what_changed)
}
}
void
Editor::update_section_box ()
{
if (selection->tracks.size() == 0 && selection->regions.size () == 0 && selection->time.length() != 0) {
_section_box->set_position (selection->time.start_time().samples(), selection->time.end_time().samples());
_section_box->show ();
} else {
_section_box->hide();
}
}
void
Editor::track_selection_changed ()
{
@ -1275,6 +1287,7 @@ Editor::track_selection_changed ()
play_solo_selection(false);
update_selection_markers ();
update_section_box ();
}
void
@ -1294,6 +1307,8 @@ Editor::time_selection_changed ()
}
update_selection_markers ();
update_section_box ();
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
(*i)->show_selection (selection->time);
}

View File

@ -94,6 +94,7 @@ gtk2_ardour_sources = [
'editor_cursors.cc',
'editor_drag.cc',
'editor_route_groups.cc',
'editor_section_box.cc',
'editor_export_audio.cc',
'editor_group_tabs.cc',
'editor_keys.cc',