(1) remove almost-never used block/unlock_property_changes() methods from PBD::Stateful (2) hide used and path columns from region list (3) detect mouse position within MIDI notes and thus allow move or trim from the same mouse mode (object or trim; first & last 1/4 of each note is for trimming

git-svn-id: svn://localhost/ardour2/branches/3.0@7823 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-09-21 15:15:06 +00:00
parent e6ecd36b26
commit 90e73a3a6d
14 changed files with 131 additions and 33 deletions

View file

@ -488,7 +488,7 @@ AudioStreamView::setup_rec_box ()
boost::dynamic_pointer_cast<AudioRegion>(RegionFactory::create (sources, plist, false)));
assert(region);
region->block_property_changes ();
region->suspend_property_changes ();
region->set_position (_trackview.session()->transport_frame(), this);
rec_regions.push_back (make_pair(region, (RegionView*) 0));
}

View file

@ -53,6 +53,8 @@ CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item, const boost
, _note(note)
, _selected(false)
, _valid (true)
, _mouse_x_fraction (-1.0)
, _mouse_y_fraction (-1.0)
{
}
@ -223,6 +225,60 @@ CanvasNoteEvent::base_color()
return 0;
}
void
CanvasNoteEvent::set_mouse_fractions (GdkEvent* ev)
{
double ix, iy;
double bx1, bx2, by1, by2;
switch (ev->type) {
case GDK_MOTION_NOTIFY:
ix = ev->motion.x;
iy = ev->motion.y;
break;
case GDK_ENTER_NOTIFY:
ix = ev->crossing.x;
iy = ev->crossing.y;
break;
case GDK_BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
ix = ev->button.x;
iy = ev->button.y;
break;
default:
_mouse_x_fraction = -1.0;
_mouse_y_fraction = -1.0;
return;
}
_item->get_bounds (bx1, by1, bx2, by2);
_item->w2i (ix, iy);
/* hmm, something wrong here. w2i should give item-local coordinates
but it doesn't. for now, finesse this.
*/
ix = ix - bx1;
iy = iy - by1;
/* fraction of width/height */
double xf;
double yf;
bool notify = false;
xf = ix / (bx2 - bx1);
yf = iy / (by2 - by1);
if (xf != _mouse_x_fraction || yf != _mouse_y_fraction) {
notify = true;
}
_mouse_x_fraction = xf;
_mouse_y_fraction = yf;
if (notify) {
_region.note_mouse_position (_mouse_x_fraction, _mouse_y_fraction);
}
}
bool
CanvasNoteEvent::on_event(GdkEvent* ev)
{
@ -232,22 +288,21 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
switch (ev->type) {
case GDK_ENTER_NOTIFY:
_region.note_entered(this);
set_mouse_fractions (ev);
_region.note_entered (this);
break;
case GDK_LEAVE_NOTIFY:
set_mouse_fractions (ev);
_region.note_left (this);
break;
case GDK_MOTION_NOTIFY:
double ix, iy;
ix = ev->motion.x;
iy = ev->motion.y;
_item->w2i (ix, iy);
cerr << "note motion at " << ix << ',' << iy << endl;
set_mouse_fractions (ev);
break;
case GDK_BUTTON_PRESS:
set_mouse_fractions (ev);
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
show_channel_selector();
return true;
@ -255,6 +310,7 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
break;
case GDK_BUTTON_RELEASE:
set_mouse_fractions (ev);
if (ev->button.button == 3 && Keyboard::no_modifiers_active (ev->button.state)) {
return true;
}
@ -267,6 +323,13 @@ CanvasNoteEvent::on_event(GdkEvent* ev)
return false;
}
bool
CanvasNoteEvent::mouse_near_ends () const
{
return (_mouse_x_fraction >= 0.0 && _mouse_x_fraction < 0.25) ||
(_mouse_x_fraction >= 0.75 && _mouse_x_fraction < 1.0);
}
} // namespace Canvas
} // namespace Gnome

View file

@ -139,7 +139,9 @@ class CanvasNoteEvent : virtual public sigc::trackable
/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
static const uint32_t midi_channel_colors[16];
protected:
bool mouse_near_ends () const;
protected:
enum State { None, Pressed, Dragging };
MidiRegionView& _region;
@ -151,6 +153,10 @@ protected:
bool _own_note;
bool _selected;
bool _valid;
float _mouse_x_fraction;
float _mouse_y_fraction;
void set_mouse_fractions (GdkEvent*);
};
} // namespace Gnome

View file

@ -476,6 +476,9 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
static Gdk::Cursor* timebar_cursor;
static Gdk::Cursor* transparent_cursor;
Gdk::Cursor* get_canvas_cursor () const { return current_canvas_cursor; }
void set_canvas_cursor (Gdk::Cursor*);
protected:
void map_transport_state ();
void map_position_change (framepos_t);
@ -686,8 +689,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
Gtk::VBox vpacker;
Gdk::Cursor* current_canvas_cursor;
void set_canvas_cursor ();
Gdk::Cursor* which_grabber_cursor ();
void set_canvas_cursor ();
ArdourCanvas::Canvas* track_canvas;

View file

@ -917,6 +917,14 @@ Editor::horizontal_position () const
{
return frame_to_unit (leftmost_frame);
}
void
Editor::set_canvas_cursor (Gdk::Cursor* cursor)
{
if (is_drawable()) {
track_canvas->get_window()->set_cursor(*cursor);
}
}
bool
Editor::track_canvas_key_press (GdkEventKey* event)

View file

@ -3769,7 +3769,7 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
}
}
} else {
_region->note_dropped (_primary, total_dx(), - total_dy());
_region->note_dropped (_primary, total_dx(), total_dy());
}
}

View file

@ -35,6 +35,7 @@
#include "ardour_ui.h"
#include "actions.h"
#include "canvas-note.h"
#include "editor.h"
#include "time_axis_view.h"
#include "audio_time_axis.h"
@ -677,14 +678,16 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case NoteItem:
if (internal_editing()) {
/* trim notes if we're in internal edit mode and near the ends of the note */
_drags->set (new NoteResizeDrag (this, item), event);
ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
if (cn->mouse_near_ends()) {
_drags->set (new NoteResizeDrag (this, item), event);
} else {
_drags->set (new NoteDrag (this, item), event);
}
}
return true;
case StreamItem:
cerr << "press on stream item, internal? " << internal_editing() << " MIDI ? "
<< dynamic_cast<MidiTimeAxisView*>(clicked_axisview)
<< endl;
if (internal_editing()) {
if (dynamic_cast<MidiTimeAxisView*> (clicked_axisview)) {
_drags->set (new RegionCreateDrag (this, item, clicked_axisview), event);
@ -718,7 +721,12 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
switch (item_type) {
case NoteItem:
if (internal_editing()) {
_drags->set (new NoteDrag (this, item), event);
ArdourCanvas::CanvasNote* cn = dynamic_cast<ArdourCanvas::CanvasNote*> (item);
if (cn->mouse_near_ends()) {
_drags->set (new NoteResizeDrag (this, item), event);
} else {
_drags->set (new NoteDrag (this, item), event);
}
return true;
}
break;

View file

@ -89,8 +89,8 @@ EditorRegions::EditorRegions (Editor* e)
_display.append_column (_("G"), _columns.glued);
_display.append_column (_("M"), _columns.muted);
_display.append_column (_("O"), _columns.opaque);
_display.append_column (_("Used"), _columns.used);
_display.append_column (_("Path"), _columns.path);
// _display.append_column (_("Used"), _columns.used);
// _display.append_column (_("Path"), _columns.path);
_display.set_headers_visible (true);
//_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH);
@ -461,10 +461,6 @@ EditorRegions::selection_changed ()
// they could have clicked on a row that is just a placeholder, like "Hidden"
if (region) {
cerr << "Selected region has use count "
<< _session->playlists->region_use_count (region)
<< endl;
if (region->automatic()) {
_display.get_selection()->unselect(*i);

View file

@ -49,6 +49,7 @@
#include "canvas-hit.h"
#include "canvas-note.h"
#include "canvas-program-change.h"
#include "editor.h"
#include "ghostregion.h"
#include "gui_thread.h"
#include "keyboard.h"
@ -2646,6 +2647,10 @@ MidiRegionView::change_channel(uint8_t channel)
void
MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
{
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
pre_enter_cursor = editor->get_canvas_cursor ();
if (_mouse_state == SelectTouchDragging) {
note_selected (ev, true);
}
@ -2656,17 +2661,28 @@ MidiRegionView::note_entered(ArdourCanvas::CanvasNoteEvent* ev)
void
MidiRegionView::note_left (ArdourCanvas::CanvasNoteEvent* note)
{
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
(*i)->hide_velocity ();
}
trackview.editor().hide_verbose_canvas_cursor ();
editor->hide_verbose_canvas_cursor ();
editor->set_canvas_cursor (pre_enter_cursor);
}
void
MidiRegionView::note_motion (float fraction)
MidiRegionView::note_mouse_position (float x_fraction, float y_fraction)
{
cerr << "Now at " << fraction << " within note\n";
Editor* editor = dynamic_cast<Editor*>(&trackview.editor());
if (x_fraction > 0.0 && x_fraction < 0.25) {
editor->set_canvas_cursor (editor->left_side_trim_cursor);
} else if (x_fraction >= 0.75 && x_fraction < 1.0) {
editor->set_canvas_cursor (editor->right_side_trim_cursor);
} else {
editor->set_canvas_cursor (pre_enter_cursor);
}
}
void

View file

@ -190,9 +190,11 @@ class MidiRegionView : public RegionView
void apply_diff_as_subcommand();
void abort_command();
Gdk::Cursor* pre_enter_cursor;
void note_entered(ArdourCanvas::CanvasNoteEvent* ev);
void note_left(ArdourCanvas::CanvasNoteEvent* ev);
void note_motion (float fraction);
void note_mouse_position (float xfraction, float yfraction);
void unique_select(ArdourCanvas::CanvasNoteEvent* ev);
void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add, bool extend=false);
void note_deselected(ArdourCanvas::CanvasNoteEvent* ev);
@ -432,7 +434,6 @@ class MidiRegionView : public RegionView
void get_events (Events& e, Evoral::Sequence<Evoral::MusicalTime>::NoteOperator op, uint8_t val, int chan_mask = 0);
void display_program_changes_on_channel (uint8_t);
};

View file

@ -459,7 +459,7 @@ MidiStreamView::setup_rec_box ()
(RegionFactory::create (sources, plist, false)));
assert(region);
region->block_property_changes ();
region->suspend_property_changes ();
region->set_position (_trackview.session()->transport_frame(), this);
rec_regions.push_back (make_pair(region, (RegionView*)0));

View file

@ -1310,7 +1310,7 @@ Region::send_change (const PropertyChange& what_changed)
Stateful::send_change (what_changed);
if (!_no_property_changes) {
if (!Stateful::frozen()) {
/* Try and send a shared_pointer unless this is part of the constructor.
If so, do nothing.

View file

@ -86,10 +86,9 @@ class Stateful {
virtual void suspend_property_changes ();
virtual void resume_property_changes ();
virtual bool frozen() const { return _frozen; }
void unlock_property_changes () { _no_property_changes = false; }
void block_property_changes () { _no_property_changes = true; }
protected:
void add_instant_xml (XMLNode&, const sys::path& directory_path);
@ -108,7 +107,6 @@ class Stateful {
XMLNode *_instant_xml;
PBD::ID _id;
int32_t _frozen;
bool _no_property_changes;
PBD::PropertyChange _pending_changed;
Glib::Mutex _lock;

View file

@ -40,7 +40,6 @@ int Stateful::loading_state_version = 0;
Stateful::Stateful ()
: _frozen (0)
, _no_property_changes (false)
, _properties (new OwnedPropertyList)
{
_extra_xml = 0;