fix ordering of cut/copied regions when pasting; ctrl-click now does the right thing the first time its used on a region; fix missing click and other dubious behaviour in new sessions caused by not connecting to Configuration::ParameterChanged in the new session constructor

git-svn-id: svn://localhost/ardour2/trunk@1331 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2007-01-17 01:42:44 +00:00
parent d3071f84e5
commit 762d2ae936
13 changed files with 201 additions and 83 deletions

View File

@ -266,7 +266,7 @@ ActionManager::toggle_config_state (const char* group, const char* action, bool
if (tact) {
bool x = (Config->*get)();
if (x != tact->get_active()) {
(Config->*set) (!x);
}

View File

@ -19,6 +19,7 @@
*/
#include <pbd/convert.h>
#include <pbd/stacktrace.h>
#include <gtkmm2ext/utils.h>

View File

@ -28,6 +28,7 @@
#include <pbd/convert.h>
#include <pbd/error.h>
#include <pbd/stacktrace.h>
#include <pbd/memento_command.h>
#include <gtkmm/image.h>
@ -3030,7 +3031,6 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32
return;
}
if ((pl = ds->playlist()) != 0) {
pl->get_equivalent_regions (basis->region(), results);
}
@ -3052,6 +3052,10 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
return false;
}
if (press) {
button_release_can_deselect = false;
}
if (op == Selection::Toggle || op == Selection::Set) {
mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click),
@ -4292,3 +4296,17 @@ Editor::idle_visual_changer ()
return 0;
}
struct EditorOrderTimeAxisSorter {
bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
return a->order < b->order;
}
};
void
Editor::sort_track_selection ()
{
EditorOrderTimeAxisSorter cmp;
selection->tracks.sort (cmp);
}

View File

@ -419,6 +419,8 @@ class Editor : public PublicEditor
CrossfadeView* clicked_crossfadeview;
ControlPoint* clicked_control_point;
void sort_track_selection ();
void get_relevant_audio_tracks (std::set<AudioTimeAxisView*>& relevant_tracks);
void mapover_audio_tracks (sigc::slot<void,AudioTimeAxisView&,uint32_t> sl);

View File

@ -82,7 +82,7 @@ Editor::kbd_do_split (GdkEvent* ev)
nframes_t where = event_frame (ev);
if (entered_regionview) {
if (selection->regions.find (entered_regionview) != selection->regions.end()) {
if (selection->regions.contains (entered_regionview)) {
split_regions_at (where, selection->regions);
} else {
RegionSelection s;

View File

@ -77,6 +77,9 @@ Editor::show_editor_mixer (bool yn)
}
} else {
sort_track_selection ();
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv;

View File

@ -1351,27 +1351,20 @@ Editor::select_all_within (nframes_t start, nframes_t end, double top, double bo
(*iter)->get_selectables (start, end, top, bot, touched);
}
cerr << "select all within found " << touched.size() << endl;
begin_reversible_command (_("select all within"));
switch (op) {
case Selection::Add:
case Selection::Toggle:
cerr << "toggle\n";
selection->add (touched);
break;
case Selection::Set:
cerr << "set\n";
selection->set (touched);
break;
case Selection::Extend:
cerr << "extend\n";
/* not defined yet */
break;
}
cerr << "selection now has " << selection->points.size() << endl;
commit_reversible_command ();
return !touched.empty();
}
@ -2166,6 +2159,8 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& n
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
sort_track_selection ();
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
boost::shared_ptr<AudioRegion> current;
@ -2227,6 +2222,8 @@ Editor::separate_region_from_selection ()
boost::shared_ptr<Playlist> playlist;
sort_track_selection ();
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv;
@ -2333,6 +2330,8 @@ Editor::crop_region_to_selection ()
} else {
sort_track_selection ();
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
AudioTimeAxisView* atv;
@ -2949,17 +2948,33 @@ struct lt_playlist {
}
};
struct PlaylistMapping {
TimeAxisView* tv;
boost::shared_ptr<AudioPlaylist> pl;
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
};
void
Editor::cut_copy_regions (CutCopyOp op)
{
typedef std::map<boost::shared_ptr<AudioPlaylist>,boost::shared_ptr<AudioPlaylist> > PlaylistMapping;
PlaylistMapping pmap;
nframes_t first_position = max_frames;
/* we can't use a std::map here because the ordering is important, and we can't trivially sort
a map when we want ordered access to both elements. i think.
*/
vector<PlaylistMapping> pmap;
nframes_t first_position = max_frames;
set<PlaylistState, lt_playlist> freezelist;
pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
/* get ordering correct before we cut/copy */
selection->regions.sort_by_position_and_track ();
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
first_position = min ((*x)->region()->position(), first_position);
if (op == Cut || op == Clear) {
@ -2972,66 +2987,94 @@ Editor::cut_copy_regions (CutCopyOp op)
before.before = &pl->get_state();
insert_result = freezelist.insert (before);
if (insert_result.second) {
pl->freeze ();
}
}
}
TimeAxisView* tv = &(*x)->get_trackview();
vector<PlaylistMapping>::iterator z;
for (z = pmap.begin(); z != pmap.end(); ++z) {
if ((*z).tv == tv) {
break;
}
}
if (z == pmap.end()) {
pmap.push_back (PlaylistMapping (tv));
}
}
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
if (!pl) {
/* impossible, but this handles it for the future */
continue;
}
TimeAxisView& tv = (*x)->get_trackview();
boost::shared_ptr<AudioPlaylist> npl;
RegionSelection::iterator tmp;
tmp = x;
++tmp;
if (pl) {
PlaylistMapping::iterator pi = pmap.find (pl);
vector<PlaylistMapping>::iterator z;
for (z = pmap.begin(); z != pmap.end(); ++z) {
if ((*z).tv == &tv) {
break;
}
}
assert (z != pmap.end());
if (!(*z).pl) {
npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
npl->freeze();
(*z).pl = npl;
} else {
npl = (*z).pl;
}
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
switch (op) {
case Cut:
if (!ar) break;
if (pi == pmap.end()) {
npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
npl->freeze();
pmap[pl] = npl;
} else {
npl = pi->second;
}
// FIXME
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
switch (op) {
case Cut:
if (!ar) break;
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
pl->remove_region (((*x)->region()));
break;
case Copy:
if (!ar) break;
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
break;
case Clear:
pl->remove_region (((*x)->region()));
break;
}
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
pl->remove_region (((*x)->region()));
break;
case Copy:
if (!ar) break;
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
break;
case Clear:
pl->remove_region (((*x)->region()));
break;
}
x = tmp;
}
list<boost::shared_ptr<Playlist> > foo;
for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
foo.push_back (i->second);
/* the pmap is in the same order as the tracks in which selected regions occured */
for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
(*i).pl->thaw();
foo.push_back ((*i).pl);
}
if (!foo.empty()) {
cut_buffer->set (foo);
}
@ -3095,15 +3138,19 @@ Editor::paste_internal (nframes_t position, float times)
TrackSelection::iterator i;
size_t nth;
/* get everything in the correct order */
sort_track_selection ();
for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
/* undo/redo is handled by individual tracks */
if ((*i)->paste (position, times, *cut_buffer, nth)) {
commit = true;
}
}
if (commit) {
commit_reversible_command ();
}
@ -3129,6 +3176,8 @@ Editor::paste_named_selection (float times)
chunk = ns->playlists.begin();
begin_reversible_command (_("paste chunk"));
sort_track_selection ();
for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
@ -3241,8 +3290,6 @@ Editor::reset_point_selection ()
{
/* reset all selected points to the relevant default value */
cerr << "point selection has " << selection->points.size() << " entries\n";
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);

View File

@ -22,22 +22,13 @@
#include "region_view.h"
#include "region_selection.h"
#include "time_axis_view.h"
using namespace ARDOUR;
using namespace PBD;
using namespace sigc;
bool
RegionComparator::operator() (const RegionView* a, const RegionView* b) const
{
if (a == b) {
return false;
} else {
return a < b;
}
}
RegionSelection::RegionSelection ()
{
_current_start = 0;
@ -46,9 +37,8 @@ RegionSelection::RegionSelection ()
RegionSelection::RegionSelection (const RegionSelection& other)
{
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
add (*i, false);
add (*i);
}
_current_start = other._current_start;
_current_end = other._current_end;
@ -64,7 +54,7 @@ RegionSelection::operator= (const RegionSelection& other)
clear_all();
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
add (*i, false);
add (*i);
}
_current_start = other._current_start;
@ -85,11 +75,11 @@ RegionSelection::clear_all()
bool RegionSelection::contains (RegionView* rv)
{
return this->find (rv) != end();
return find (begin(), end(), rv) != end();
}
void
RegionSelection::add (RegionView* rv, bool dosort)
RegionSelection::add (RegionView* rv)
{
if (contains (rv)) {
/* we already have it */
@ -106,11 +96,11 @@ RegionSelection::add (RegionView* rv, bool dosort)
_current_end = rv->region()->last_frame();
}
insert (rv);
push_back (rv);
// add to layer sorted list
add_to_layer (rv);
}
void
@ -124,7 +114,7 @@ RegionSelection::remove (RegionView* rv)
{
RegionSelection::iterator i;
if ((i = this->find (rv)) != end()) {
if ((i = find (begin(), end(), rv)) != end()) {
erase (i);
@ -198,7 +188,7 @@ RegionSelection::add_to_layer (RegionView * rv)
}
struct RegionSortByTime {
bool operator() (const RegionView* a, const RegionView* b) {
bool operator() (const RegionView* a, const RegionView* b) const {
return a->region()->position() < b->region()->position();
}
};
@ -217,3 +207,37 @@ RegionSelection::by_position (list<RegionView*>& foo) const
foo.sort (sorter);
return;
}
struct RegionSortByTrack {
bool operator() (const RegionView* a, const RegionView* b) const {
/* really, track and position */
if (a->get_trackview().order == b->get_trackview().order) {
return a->region()->position() < b->region()->position();
} else {
return a->get_trackview().order < b->get_trackview().order;
}
}
};
void
RegionSelection::by_track (list<RegionView*>& foo) const
{
list<RegionView*>::const_iterator i;
RegionSortByTrack sorter;
for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
foo.push_back (*i);
}
foo.sort (sorter);
return;
}
void
RegionSelection::sort_by_position_and_track ()
{
RegionSortByTrack sorter;
sort (sorter);
}

View File

@ -29,11 +29,7 @@ using std::set;
class RegionView;
struct RegionComparator {
bool operator() (const RegionView* a, const RegionView* b) const;
};
class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable
class RegionSelection : public std::list<RegionView*>, public sigc::trackable
{
public:
RegionSelection();
@ -41,9 +37,10 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
RegionSelection& operator= (const RegionSelection&);
void add (RegionView*, bool dosort = true);
void add (RegionView*);
bool remove (RegionView*);
bool contains (RegionView*);
void sort_by_position_and_track ();
void clear_all();
@ -51,14 +48,15 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
return _current_start;
}
/* collides with list<>::end */
/* "end" collides with list<>::end */
nframes_t end_frame () const {
return _current_end;
}
const list<RegionView *> & by_layer() const { return _bylayer; }
void by_position (list<RegionView*>&) const;
const std::list<RegionView *>& by_layer() const { return _bylayer; }
void by_position (std::list<RegionView*>&) const;
void by_track (std::list<RegionView*>&) const;
private:
void remove_it (RegionView*);

View File

@ -232,6 +232,11 @@ class TimeAxisViewItem : public Selectable
ArdourCanvas::Text* get_name_text();
/**
* Returns the time axis that this item is upon
*/
TimeAxisView& get_trackview() const { return trackview; }
/**
* Sets the samples per unit of this item.
* this item is used to determine the relative visual size and position of this item

View File

@ -27,9 +27,13 @@ class ConfigVariableBase {
virtual void add_to_node (XMLNode& node) = 0;
virtual bool set_from_node (const XMLNode& node, Owner owner) = 0;
protected:
std::string _name;
Owner _owner;
void notify ();
void miss ();
};
template<class T>
@ -41,10 +45,12 @@ class ConfigVariable : public ConfigVariableBase
virtual bool set (T val, Owner owner) {
if (val == value) {
miss ();
return false;
}
value = val;
_owner = (ConfigVariableBase::Owner)(_owner |owner);
notify ();
return true;
}

View File

@ -317,3 +317,16 @@ Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
#undef CONFIG_VARIABLE
#undef CONFIG_VARIABLE_SPECIAL
}
void
ConfigVariableBase::notify ()
{
// placeholder for any debugging desired when a config variable is modified
}
void
ConfigVariableBase::miss ()
{
// placeholder for any debugging desired when a config variable
// is set but to the same value as it already has
}

View File

@ -368,7 +368,6 @@ Session::Session (AudioEngine &eng,
if (master_out_channels) {
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
r->set_remote_control_id (control_id);
cerr << "master bus has remote control ID " << r->remote_control_id() << endl;
rl.push_back (r);
} else {
@ -396,6 +395,8 @@ Session::Session (AudioEngine &eng,
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
if (was_dirty) {
DirtyChanged (); /* EMIT SIGNAL */
}