TrackEventRef is dead.
This commit is contained in:
parent
4b89959a42
commit
98546885fa
232
jsong.cpp
232
jsong.cpp
|
@ -7,6 +7,110 @@
|
|||
#include <cassert>
|
||||
|
||||
namespace Jacker {
|
||||
|
||||
enum {
|
||||
JSongVersion = 2,
|
||||
};
|
||||
|
||||
class JSongWriter {
|
||||
public:
|
||||
typedef std::map<Pattern *, int> Pattern2IdMap;
|
||||
Pattern2IdMap pattern2id;
|
||||
|
||||
void collect(Json::Value &root, PatternEvent &event) {
|
||||
root["frame"] = event.frame;
|
||||
root["channel"] = event.channel;
|
||||
root["param"] = event.param;
|
||||
root["value"] = event.value;
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Pattern &pattern) {
|
||||
root["name"] = pattern.name;
|
||||
root["length"] = pattern.get_length();
|
||||
root["channel_count"] = pattern.get_channel_count();
|
||||
|
||||
Json::Value events;
|
||||
|
||||
for (Pattern::iterator iter = pattern.begin();
|
||||
iter != pattern.end(); ++iter) {
|
||||
Json::Value event;
|
||||
collect(event, iter->second);
|
||||
if (!event.empty())
|
||||
events.append(event);
|
||||
}
|
||||
|
||||
if (!events.empty()) {
|
||||
root["events"] = events;
|
||||
}
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Song::Event &event) {
|
||||
Pattern2IdMap::iterator iter = pattern2id.find(event.pattern);
|
||||
if (iter == pattern2id.end())
|
||||
return;
|
||||
root["frame"] = event.frame;
|
||||
root["track"] = event.track;
|
||||
root["pattern"] = iter->second;
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Song &song) {
|
||||
Json::Value events;
|
||||
|
||||
for (Song::iterator iter = song.begin();
|
||||
iter != song.end(); ++iter) {
|
||||
Json::Value event;
|
||||
collect(event, iter->second);
|
||||
if (!event.empty())
|
||||
events.append(event);
|
||||
}
|
||||
|
||||
if (!events.empty()) {
|
||||
root["events"] = events;
|
||||
}
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Model &model) {
|
||||
root["format"] = "jacker-song";
|
||||
root["version"] = JSongVersion;
|
||||
root["end_cue"] = model.end_cue;
|
||||
root["frames_per_beat"] = model.frames_per_beat;
|
||||
root["beats_per_bar"] = model.beats_per_bar;
|
||||
root["beats_per_minute"] = model.beats_per_minute;
|
||||
|
||||
Json::Value patterns;
|
||||
|
||||
int index = 0;
|
||||
for (PatternList::iterator iter = model.patterns.begin();
|
||||
iter != model.patterns.end(); ++iter) {
|
||||
Json::Value pattern;
|
||||
collect(pattern, *(*iter));
|
||||
if (!pattern.empty()) {
|
||||
patterns.append(pattern);
|
||||
pattern2id.insert(Pattern2IdMap::value_type(*iter,index));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patterns.empty()) {
|
||||
root["patterns"] = patterns;
|
||||
}
|
||||
|
||||
Json::Value song;
|
||||
collect(song, model.song);
|
||||
if (!song.empty()) {
|
||||
root["song"] = song;
|
||||
}
|
||||
}
|
||||
|
||||
void write(Json::Value &root, const std::string &filepath) {
|
||||
assert(!root.empty());
|
||||
std::ofstream out(filepath.c_str());
|
||||
assert(out);
|
||||
out << root;
|
||||
out.close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class JSongReader {
|
||||
public:
|
||||
|
@ -53,8 +157,9 @@ public:
|
|||
patterns.push_back(&pattern);
|
||||
}
|
||||
|
||||
bool build(const Json::Value &root, Track::Event &event) {
|
||||
bool build(const Json::Value &root, Song::Event &event) {
|
||||
extract(root["frame"], event.frame);
|
||||
extract(root["track"], event.track);
|
||||
int pattern_index = -1;
|
||||
if (!extract(root["pattern"], pattern_index))
|
||||
return false;
|
||||
|
@ -64,15 +169,12 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void build(const Json::Value &root, Track &track) {
|
||||
extract(root["name"], track.name);
|
||||
extract(root["order"], track.order);
|
||||
|
||||
void build(const Json::Value &root, Song &song) {
|
||||
const Json::Value events = root["events"];
|
||||
for (size_t i = 0; i < events.size(); ++i) {
|
||||
Track::Event event;
|
||||
Song::Event event;
|
||||
if (build(events[i], event))
|
||||
track.add_event(event);
|
||||
song.add_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,11 +191,8 @@ public:
|
|||
build(patterns[i], pattern);
|
||||
}
|
||||
|
||||
const Json::Value tracks = root["tracks"];
|
||||
for (size_t i = 0; i < tracks.size(); ++i) {
|
||||
Track &track = model.new_track();
|
||||
build(tracks[i], track);
|
||||
}
|
||||
const Json::Value song = root["song"];
|
||||
build(song, model.song);
|
||||
}
|
||||
|
||||
bool read(Json::Value &root, const std::string &filepath) {
|
||||
|
@ -109,115 +208,6 @@ public:
|
|||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class JSongWriter {
|
||||
public:
|
||||
typedef std::map<Pattern *, int> Pattern2IdMap;
|
||||
Pattern2IdMap pattern2id;
|
||||
|
||||
void collect(Json::Value &root, PatternEvent &event) {
|
||||
root["frame"] = event.frame;
|
||||
root["channel"] = event.channel;
|
||||
root["param"] = event.param;
|
||||
root["value"] = event.value;
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Pattern &pattern) {
|
||||
root["name"] = pattern.name;
|
||||
root["length"] = pattern.get_length();
|
||||
root["channel_count"] = pattern.get_channel_count();
|
||||
|
||||
Json::Value events;
|
||||
|
||||
for (Pattern::iterator iter = pattern.begin();
|
||||
iter != pattern.end(); ++iter) {
|
||||
Json::Value event;
|
||||
collect(event, iter->second);
|
||||
if (!event.empty())
|
||||
events.append(event);
|
||||
}
|
||||
|
||||
if (!events.empty()) {
|
||||
root["events"] = events;
|
||||
}
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, TrackEvent &event) {
|
||||
Pattern2IdMap::iterator iter = pattern2id.find(event.pattern);
|
||||
if (iter == pattern2id.end())
|
||||
return;
|
||||
root["frame"] = event.frame;
|
||||
root["pattern"] = iter->second;
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Track &track) {
|
||||
root["name"] = track.name;
|
||||
root["order"] = track.order;
|
||||
|
||||
Json::Value events;
|
||||
|
||||
for (Track::iterator iter = track.begin();
|
||||
iter != track.end(); ++iter) {
|
||||
Json::Value event;
|
||||
collect(event, iter->second);
|
||||
if (!event.empty())
|
||||
events.append(event);
|
||||
}
|
||||
|
||||
if (!events.empty()) {
|
||||
root["events"] = events;
|
||||
}
|
||||
}
|
||||
|
||||
void collect(Json::Value &root, Model &model) {
|
||||
root["format"] = "jacker-song";
|
||||
root["end_cue"] = model.end_cue;
|
||||
root["frames_per_beat"] = model.frames_per_beat;
|
||||
root["beats_per_bar"] = model.beats_per_bar;
|
||||
root["beats_per_minute"] = model.beats_per_minute;
|
||||
|
||||
Json::Value patterns;
|
||||
|
||||
int index = 0;
|
||||
for (PatternList::iterator iter = model.patterns.begin();
|
||||
iter != model.patterns.end(); ++iter) {
|
||||
Json::Value pattern;
|
||||
collect(pattern, *(*iter));
|
||||
if (!pattern.empty()) {
|
||||
patterns.append(pattern);
|
||||
pattern2id.insert(Pattern2IdMap::value_type(*iter,index));
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!patterns.empty()) {
|
||||
root["patterns"] = patterns;
|
||||
}
|
||||
|
||||
Json::Value tracks;
|
||||
for (TrackArray::iterator iter = model.tracks.begin();
|
||||
iter != model.tracks.end(); ++iter) {
|
||||
Json::Value track;
|
||||
collect(track, *(*iter));
|
||||
if (!track.empty()) {
|
||||
tracks.append(track);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tracks.empty()) {
|
||||
root["tracks"] = tracks;
|
||||
}
|
||||
}
|
||||
|
||||
void write(Json::Value &root, const std::string &filepath) {
|
||||
assert(!root.empty());
|
||||
std::ofstream out(filepath.c_str());
|
||||
assert(out);
|
||||
out << root;
|
||||
out.close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool read_jsong(Model &model, const std::string &filepath) {
|
||||
JSongReader reader;
|
||||
|
|
12
main.cpp
12
main.cpp
|
@ -360,12 +360,12 @@ public:
|
|||
bool found = false;
|
||||
Pattern *active_pattern = pattern_view->get_pattern();
|
||||
if (active_pattern) {
|
||||
TrackEventRefList refs;
|
||||
model.find_events(frame, refs);
|
||||
if (!refs.empty()) {
|
||||
TrackEventRefList::iterator iter;
|
||||
for (iter = refs.begin(); iter != refs.end(); ++iter) {
|
||||
TrackEvent &evt = iter->iter->second;
|
||||
Song::IterList events;
|
||||
model.song.find_events(frame, events);
|
||||
if (!events.empty()) {
|
||||
Song::IterList::iterator iter;
|
||||
for (iter = events.begin(); iter != events.end(); ++iter) {
|
||||
Song::Event &evt = (*iter)->second;
|
||||
if (evt.pattern == active_pattern) {
|
||||
found = true;
|
||||
pattern_view->set_play_position(frame - evt.frame);
|
||||
|
|
52
model.cpp
52
model.cpp
|
@ -192,9 +192,6 @@ Pattern::iterator Pattern::get_event(int frame, int channel, int param) {
|
|||
}
|
||||
|
||||
void Pattern::update_keys() {
|
||||
typedef std::list<Event> EventList;
|
||||
typedef std::list<Pattern::iterator> IterList;
|
||||
|
||||
IterList dead_iters;
|
||||
EventList events;
|
||||
|
||||
|
@ -243,22 +240,21 @@ int SongEvent::get_last_frame() const {
|
|||
//=============================================================================
|
||||
|
||||
Song::Song() {
|
||||
order = -1;
|
||||
}
|
||||
|
||||
Song::iterator Song::add_event(const Event &event) {
|
||||
return BaseClass::add_event(event);
|
||||
}
|
||||
|
||||
Song::iterator Song::add_event(int frame, Pattern &pattern) {
|
||||
return add_event(Event(frame, pattern));
|
||||
Song::iterator Song::add_event(int frame, int track, Pattern &pattern) {
|
||||
return add_event(Event(frame, track, pattern));
|
||||
}
|
||||
|
||||
Song::iterator Song::get_event(int frame) {
|
||||
return BaseClass::find(frame);
|
||||
}
|
||||
|
||||
void Song::find_events(int frame, EventList &events) {
|
||||
void Song::find_events(int frame, IterList &events) {
|
||||
events.clear();
|
||||
Song::iterator iter;
|
||||
for (iter = begin(); iter != end(); ++iter) {
|
||||
|
@ -270,6 +266,30 @@ void Song::find_events(int frame, EventList &events) {
|
|||
}
|
||||
}
|
||||
|
||||
void Song::update_keys() {
|
||||
IterList dead_iters;
|
||||
EventList events;
|
||||
|
||||
for (iterator iter = begin(); iter != end(); ++iter) {
|
||||
if (iter->first != iter->second.frame) {
|
||||
events.push_back(iter->second);
|
||||
dead_iters.push_back(iter);
|
||||
}
|
||||
}
|
||||
|
||||
for (IterList::iterator iter = dead_iters.begin();
|
||||
iter != dead_iters.end(); ++iter) {
|
||||
erase(*iter);
|
||||
}
|
||||
|
||||
for (EventList::iterator iter = events.begin();
|
||||
iter != events.end(); ++iter) {
|
||||
if (iter->frame == -1) // skip
|
||||
continue;
|
||||
add_event(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
Measure::Measure() {
|
||||
|
@ -305,7 +325,7 @@ void Model::reset() {
|
|||
frames_per_beat = 4;
|
||||
beats_per_bar = 4;
|
||||
patterns.clear();
|
||||
tracks.clear();
|
||||
song.clear();
|
||||
}
|
||||
|
||||
Pattern &Model::new_pattern() {
|
||||
|
@ -315,22 +335,6 @@ Pattern &Model::new_pattern() {
|
|||
return *pattern;
|
||||
}
|
||||
|
||||
Track &Model::new_track() {
|
||||
Track *track = new Track();
|
||||
tracks.push_back(track);
|
||||
renumber_tracks();
|
||||
return *track;
|
||||
}
|
||||
|
||||
void Model::renumber_tracks() {
|
||||
TrackArray::iterator iter;
|
||||
int index = 0;
|
||||
for (iter = tracks.begin(); iter != tracks.end(); ++iter) {
|
||||
(*iter)->order = index;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
int Model::get_track_count() const {
|
||||
return 8;
|
||||
}
|
||||
|
|
15
model.hpp
15
model.hpp
|
@ -39,6 +39,8 @@ public:
|
|||
typedef typename map::key_type Key;
|
||||
typedef typename map::mapped_type Event;
|
||||
typedef EventCollection<Map_T> BaseClass;
|
||||
typedef std::list<Event> EventList;
|
||||
typedef std::list<typename Map_T::iterator> IterList;
|
||||
|
||||
typename map::iterator add_event(const Event &event) {
|
||||
return extract_iterator<typename map::key_type, Event>(
|
||||
|
@ -175,19 +177,14 @@ struct SongEvent {
|
|||
class Song : public EventCollection< std::multimap<int,SongEvent> > {
|
||||
friend class Model;
|
||||
public:
|
||||
typedef std::list<iterator> EventList;
|
||||
|
||||
// name of track (non-unique)
|
||||
std::string name;
|
||||
// order of track
|
||||
int order;
|
||||
|
||||
iterator add_event(const Event &event);
|
||||
iterator add_event(int frame, Pattern &pattern);
|
||||
iterator add_event(int frame, int track, Pattern &pattern);
|
||||
|
||||
iterator get_event(int frame);
|
||||
|
||||
void find_events(int frame, EventList &events);
|
||||
void find_events(int frame, IterList &events);
|
||||
|
||||
void update_keys();
|
||||
protected:
|
||||
Song();
|
||||
};
|
||||
|
|
38
player.cpp
38
player.cpp
|
@ -183,28 +183,32 @@ void Player::init_message(Message &msg) {
|
|||
void Player::mix_frame() {
|
||||
assert(model);
|
||||
|
||||
Song::EventList events;
|
||||
model.song.find_events(position, events);
|
||||
Song::IterList events;
|
||||
model->song.find_events(position, events);
|
||||
if (events.empty())
|
||||
return;
|
||||
|
||||
Track::Event &event = iter->second;
|
||||
Pattern &pattern = *event.pattern;
|
||||
Pattern::iterator row_iter = pattern.begin();
|
||||
Pattern::Row row;
|
||||
pattern.collect_events(position - event.frame, row_iter, row);
|
||||
|
||||
// first run: process all cc events
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
on_cc(row.get_value(channel, ParamCCIndex),
|
||||
row.get_value(channel, ParamCCValue));
|
||||
Song::IterList::iterator iter;
|
||||
for (iter = events.begin(); iter != events.end(); ++iter) {
|
||||
Song::Event &event = (*iter)->second;
|
||||
Pattern &pattern = *event.pattern;
|
||||
Pattern::iterator row_iter = pattern.begin();
|
||||
Pattern::Row row;
|
||||
pattern.collect_events(position - event.frame, row_iter, row);
|
||||
|
||||
// first run: process all cc events
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
on_cc(row.get_value(channel, ParamCCIndex),
|
||||
row.get_value(channel, ParamCCValue));
|
||||
}
|
||||
|
||||
// second run: process volume and notes
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
on_volume(channel, row.get_value(channel, ParamVolume));
|
||||
on_note(channel, row.get_value(channel, ParamNote));
|
||||
}
|
||||
}
|
||||
|
||||
// second run: process volume and notes
|
||||
for (int channel = 0; channel < pattern.get_channel_count(); ++channel) {
|
||||
on_volume(channel, row.get_value(channel, ParamVolume));
|
||||
on_note(channel, row.get_value(channel, ParamNote));
|
||||
}
|
||||
}
|
||||
|
||||
void Player::handle_message(Message msg) {
|
||||
|
|
156
trackview.cpp
156
trackview.cpp
|
@ -207,22 +207,27 @@ void TrackView::get_event_location(int x, int y, int &frame, int &track) const {
|
|||
track = (y - origin_y)/TrackHeight;
|
||||
}
|
||||
|
||||
bool TrackView::find_event(const TrackCursor &cur, TrackEventRef &ref) {
|
||||
bool TrackView::find_event(const TrackCursor &cur, Song::iterator &event) {
|
||||
if (cur.get_track() >= model->get_track_count())
|
||||
return false;
|
||||
Track *track = &model->get_track(cur.get_track());
|
||||
Track::iterator iter = track->find_event(cur.get_frame());
|
||||
if (iter == track->end())
|
||||
Song::IterList events;
|
||||
model->song.find_events(cur.get_frame(), events);
|
||||
if (events.empty())
|
||||
return false;
|
||||
ref.track = track;
|
||||
ref.iter = iter;
|
||||
return true;
|
||||
for (Song::IterList::reverse_iterator iter = events.rbegin();
|
||||
iter != events.rend(); ++iter) {
|
||||
if ((*iter)->second.track == cur.get_track()) {
|
||||
event = *iter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TrackView::render_event(const TrackEventRef &ref) {
|
||||
bool selected = is_event_selected(ref);
|
||||
void TrackView::render_event(Song::iterator event) {
|
||||
bool selected = is_event_selected(event);
|
||||
int x,y,w,h;
|
||||
get_event_rect(ref, x, y, w, h);
|
||||
get_event_rect(event, x, y, w, h);
|
||||
// main border
|
||||
gc->set_foreground(colors[ColorBlack]);
|
||||
window->draw_rectangle(gc, false, x, y+1, w, h-3);
|
||||
|
@ -231,7 +236,7 @@ void TrackView::render_event(const TrackEventRef &ref) {
|
|||
// right shadow
|
||||
window->draw_rectangle(gc, true, x+w+1, y+2, 1, h-2);
|
||||
pango_layout->set_width((w-4)*Pango::SCALE);
|
||||
pango_layout->set_text(ref.iter->second.pattern->name.c_str());
|
||||
pango_layout->set_text(event->second.pattern->name.c_str());
|
||||
if (selected) {
|
||||
// fill
|
||||
window->draw_rectangle(gc, true, x+2, y+3, w-3, h-6);
|
||||
|
@ -250,13 +255,13 @@ void TrackView::render_event(const TrackEventRef &ref) {
|
|||
}
|
||||
}
|
||||
|
||||
void TrackView::render_track(Track &track) {
|
||||
void TrackView::render_track(int track) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
window->get_size(width, height);
|
||||
|
||||
int x,y;
|
||||
get_event_pos(0, track.order, x, y);
|
||||
get_event_pos(0, track, x, y);
|
||||
|
||||
gc->set_foreground(colors[ColorTrack]);
|
||||
window->draw_rectangle(gc, true, 0, y, width, TrackHeight);
|
||||
|
@ -272,20 +277,15 @@ bool TrackView::on_expose_event(GdkEventExpose* event) {
|
|||
window->draw_rectangle(gc, true, 0, 0, width, height);
|
||||
|
||||
// first pass: render tracks
|
||||
TrackArray::iterator track_iter;
|
||||
for (track_iter = model->tracks.begin();
|
||||
track_iter != model->tracks.end(); ++track_iter) {
|
||||
Track &track = *(*track_iter);
|
||||
for (int track = 0; track < model->get_track_count(); ++track) {
|
||||
render_track(track);
|
||||
}
|
||||
|
||||
// second pass: render events
|
||||
for (track_iter = model->tracks.begin();
|
||||
track_iter != model->tracks.end(); ++track_iter) {
|
||||
Track &track = *(*track_iter);
|
||||
for (Track::iterator iter = track.begin(); iter != track.end(); ++iter) {
|
||||
render_event(TrackEventRef(track,iter));
|
||||
}
|
||||
|
||||
for (Song::iterator iter = model->song.begin();
|
||||
iter != model->song.end(); ++iter) {
|
||||
render_event(iter);
|
||||
}
|
||||
|
||||
// draw play cursor
|
||||
|
@ -310,8 +310,9 @@ void TrackView::invalidate_play_position() {
|
|||
window->invalidate_rect(rect, true);
|
||||
}
|
||||
|
||||
bool TrackView::is_event_selected(const TrackEventRef &ref) {
|
||||
return (selection.find(ref) != selection.end());
|
||||
bool TrackView::is_event_selected(Song::iterator event) {
|
||||
return (std::find(selection.begin(), selection.end(),
|
||||
event) != selection.end());
|
||||
}
|
||||
|
||||
void TrackView::clear_selection() {
|
||||
|
@ -319,35 +320,38 @@ void TrackView::clear_selection() {
|
|||
selection.clear();
|
||||
}
|
||||
|
||||
void TrackView::select_event(const TrackEventRef &ref) {
|
||||
selection.insert(ref);
|
||||
void TrackView::select_event(Song::iterator event) {
|
||||
if (is_event_selected(event))
|
||||
return;
|
||||
selection.push_back(event);
|
||||
invalidate_selection();
|
||||
}
|
||||
|
||||
void TrackView::deselect_event(const TrackEventRef &ref) {
|
||||
void TrackView::deselect_event(Song::iterator event) {
|
||||
if (!is_event_selected(event))
|
||||
return;
|
||||
invalidate_selection();
|
||||
selection.erase(ref);
|
||||
selection.remove(event);
|
||||
}
|
||||
|
||||
void TrackView::add_track() {
|
||||
model->new_track();
|
||||
// TODO
|
||||
//model->new_track();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void TrackView::new_pattern(const TrackCursor &cur) {
|
||||
if (cur.get_track() < model->get_track_count()) {
|
||||
Track &track = model->get_track(cur.get_track());
|
||||
Pattern &pattern = model->new_pattern();
|
||||
TrackEventRef ref(track,
|
||||
track.add_event(cur.get_frame(), pattern));
|
||||
Song::iterator event = model->song.add_event(cur.get_frame(), cur.get_track(), pattern);
|
||||
clear_selection();
|
||||
select_event(ref);
|
||||
select_event(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TrackView::edit_pattern(const TrackEventRef &ref) {
|
||||
Pattern *pattern = ref.iter->second.pattern;
|
||||
void TrackView::edit_pattern(Song::iterator iter) {
|
||||
Pattern *pattern = iter->second.pattern;
|
||||
_pattern_edit_request(pattern);
|
||||
}
|
||||
|
||||
|
@ -382,19 +386,19 @@ bool TrackView::on_button_press_event(GdkEventButton* event) {
|
|||
if (event->button == 1) {
|
||||
TrackCursor cur(*this);
|
||||
cur.set_pos(event->x, event->y);
|
||||
TrackEventRef ref;
|
||||
Song::iterator evt;
|
||||
|
||||
if (!ctrl_down)
|
||||
if (!ctrl_down && (selection.size() == 1))
|
||||
clear_selection();
|
||||
|
||||
if (find_event(cur, ref)) {
|
||||
if (ctrl_down && is_event_selected(ref)) {
|
||||
deselect_event(ref);
|
||||
if (find_event(cur, evt)) {
|
||||
if (ctrl_down && is_event_selected(evt)) {
|
||||
deselect_event(evt);
|
||||
} else {
|
||||
select_event(ref);
|
||||
select_event(evt);
|
||||
if (double_click) {
|
||||
interact_mode = InteractNone;
|
||||
edit_pattern(ref);
|
||||
edit_pattern(evt);
|
||||
} else {
|
||||
interact_mode = InteractDrag;
|
||||
drag.start(event->x, event->y);
|
||||
|
@ -404,6 +408,7 @@ bool TrackView::on_button_press_event(GdkEventButton* event) {
|
|||
cur.set_frame(quantize_frame(cur.get_frame()));
|
||||
new_pattern(cur);
|
||||
} else {
|
||||
clear_selection();
|
||||
interact_mode = InteractSelect;
|
||||
drag.start(event->x, event->y);
|
||||
}
|
||||
|
@ -413,9 +418,9 @@ bool TrackView::on_button_press_event(GdkEventButton* event) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TrackView::can_resize_event(const TrackEventRef &ref, int x) {
|
||||
bool TrackView::can_resize_event(Song::iterator event, int x) {
|
||||
int ex, ey, ew, eh;
|
||||
get_event_rect(ref,ex,ey,ew,eh);
|
||||
get_event_rect(event,ex,ey,ew,eh);
|
||||
return std::abs(x - (ex+ew)) < ResizeThreshold;
|
||||
}
|
||||
|
||||
|
@ -449,9 +454,9 @@ bool TrackView::on_motion_notify_event(GdkEventMotion *event) {
|
|||
if (interact_mode == InteractNone) {
|
||||
TrackCursor cur(*this);
|
||||
cur.set_pos(event->x, event->y);
|
||||
TrackEventRef ref;
|
||||
if (find_event(cur, ref)) {
|
||||
if (can_resize_event(ref, event->x))
|
||||
Song::iterator evt;
|
||||
if (find_event(cur, evt)) {
|
||||
if (can_resize_event(evt, event->x))
|
||||
window->set_cursor(Gdk::Cursor(Gdk::SB_H_DOUBLE_ARROW));
|
||||
else
|
||||
window->set_cursor(Gdk::Cursor(Gdk::HAND1));
|
||||
|
@ -465,8 +470,8 @@ bool TrackView::on_motion_notify_event(GdkEventMotion *event) {
|
|||
invalidate_selection();
|
||||
TrackCursor cur(*this);
|
||||
cur.set_pos(drag.start_x, drag.start_y);
|
||||
TrackEventRef ref;
|
||||
if (find_event(cur, ref) && can_resize_event(ref,drag.start_x)) {
|
||||
Song::iterator evt;
|
||||
if (find_event(cur, evt) && can_resize_event(evt,drag.start_x)) {
|
||||
interact_mode = InteractResize;
|
||||
} else {
|
||||
interact_mode = InteractMove;
|
||||
|
@ -494,12 +499,11 @@ void TrackView::apply_move() {
|
|||
|
||||
bool can_move = true;
|
||||
// verify that we can move
|
||||
for (EventSet::iterator iter = selection.begin();
|
||||
for (Song::IterList::iterator iter = selection.begin();
|
||||
iter != selection.end(); ++iter) {
|
||||
const TrackEventRef &ref = *iter;
|
||||
Track::Event &event = ref.iter->second;
|
||||
Song::Event &event = (*iter)->second;
|
||||
int frame = event.frame + ofs_frame;
|
||||
int track = ref.track->order + ofs_track;
|
||||
int track = event.track + ofs_track;
|
||||
if ((frame < 0)||(track < 0)||(track >= model->get_track_count())) {
|
||||
can_move = false;
|
||||
break;
|
||||
|
@ -507,27 +511,22 @@ void TrackView::apply_move() {
|
|||
}
|
||||
|
||||
if (can_move) {
|
||||
EventSet new_selection;
|
||||
Song::IterList new_selection;
|
||||
|
||||
// verify that we can move
|
||||
for (EventSet::iterator iter = selection.begin();
|
||||
// do the actual move
|
||||
for (Song::IterList::iterator iter = selection.begin();
|
||||
iter != selection.end(); ++iter) {
|
||||
const TrackEventRef &ref = *iter;
|
||||
Track::Event event = ref.iter->second;
|
||||
Song::Event event = (*iter)->second;
|
||||
|
||||
event.frame += ofs_frame;
|
||||
int track_index = ref.track->order + ofs_track;
|
||||
event.track += ofs_track;
|
||||
|
||||
model->delete_event(ref);
|
||||
|
||||
Track &track = model->get_track(track_index);
|
||||
TrackEventRef new_ref(track,
|
||||
track.add_event(event));
|
||||
new_selection.insert(new_ref);
|
||||
model->song.erase(*iter);
|
||||
Song::iterator new_event = model->song.add_event(event);
|
||||
new_selection.push_back(new_event);
|
||||
}
|
||||
|
||||
selection.clear();
|
||||
//selection = new_selection;
|
||||
selection = new_selection;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,10 +536,9 @@ void TrackView::apply_resize() {
|
|||
get_drag_offset(ofs_frame, ofs_track);
|
||||
|
||||
// verify that we can move
|
||||
for (EventSet::iterator iter = selection.begin();
|
||||
for (Song::IterList::iterator iter = selection.begin();
|
||||
iter != selection.end(); ++iter) {
|
||||
const TrackEventRef &ref = *iter;
|
||||
Track::Event &event = ref.iter->second;
|
||||
Song::Event &event = (*iter)->second;
|
||||
int length = std::max(event.pattern->get_length() + ofs_frame,
|
||||
get_step_size());
|
||||
|
||||
|
@ -609,17 +607,17 @@ int TrackView::quantize_frame(int frame) {
|
|||
return frame - (frame%get_step_size());
|
||||
}
|
||||
|
||||
void TrackView::get_event_rect(const TrackEventRef &ref, int &x, int &y, int &w, int &h) {
|
||||
Track::Event &event = ref.iter->second;
|
||||
void TrackView::get_event_rect(Song::iterator iter, int &x, int &y, int &w, int &h) {
|
||||
Song::Event &event = iter->second;
|
||||
int frame = event.frame;
|
||||
int track = ref.track->order;
|
||||
int track = event.track;
|
||||
int length = event.pattern->get_length();
|
||||
if (moving() && is_event_selected(ref)) {
|
||||
if (moving() && is_event_selected(iter)) {
|
||||
int ofs_frame,ofs_track;
|
||||
get_drag_offset(ofs_frame, ofs_track);
|
||||
frame += ofs_frame;
|
||||
track += ofs_track;
|
||||
} else if (resizing() && is_event_selected(ref)) {
|
||||
} else if (resizing() && is_event_selected(iter)) {
|
||||
int ofs_frame,ofs_track;
|
||||
get_drag_offset(ofs_frame, ofs_track);
|
||||
length = std::max(length + ofs_frame, get_step_size());
|
||||
|
@ -635,7 +633,7 @@ void TrackView::invalidate() {
|
|||
}
|
||||
|
||||
void TrackView::invalidate_selection() {
|
||||
EventSet::iterator iter;
|
||||
Song::IterList::iterator iter;
|
||||
for (iter = selection.begin(); iter != selection.end(); ++iter) {
|
||||
int x,y,w,h;
|
||||
get_event_rect(*iter, x, y, w, h);
|
||||
|
@ -647,9 +645,9 @@ void TrackView::invalidate_selection() {
|
|||
|
||||
void TrackView::erase_events() {
|
||||
invalidate_selection();
|
||||
EventSet::iterator iter;
|
||||
Song::IterList::iterator iter;
|
||||
for (iter = selection.begin(); iter != selection.end(); ++iter) {
|
||||
iter->track->erase(iter->iter);
|
||||
model->song.erase(*iter);
|
||||
}
|
||||
|
||||
selection.clear();
|
||||
|
|
|
@ -89,8 +89,6 @@ public:
|
|||
typedef sigc::signal<void, Pattern *> type_pattern_edit_request;
|
||||
typedef sigc::signal<void, TrackView *, GdkEventButton*> type_context_menu;
|
||||
|
||||
typedef std::set<TrackEventRef> EventSet;
|
||||
|
||||
TrackView(BaseObjectType* cobject,
|
||||
const Glib::RefPtr<Gtk::Builder>& builder);
|
||||
|
||||
|
@ -123,19 +121,19 @@ public:
|
|||
void get_event_length(int w, int h, int &length, int &track) const;
|
||||
void get_event_location(int x, int y, int &frame, int &track) const;
|
||||
|
||||
void get_event_rect(const TrackEventRef &ref, int &x, int &y, int &w, int &h);
|
||||
bool find_event(const TrackCursor &cursor, TrackEventRef &ref);
|
||||
void get_event_rect(Song::iterator event, int &x, int &y, int &w, int &h);
|
||||
bool find_event(const TrackCursor &cursor, Song::iterator &event);
|
||||
|
||||
void clear_selection();
|
||||
void select_event(const TrackEventRef &ref);
|
||||
void deselect_event(const TrackEventRef &ref);
|
||||
bool is_event_selected(const TrackEventRef &ref);
|
||||
void select_event(Song::iterator event);
|
||||
void deselect_event(Song::iterator event);
|
||||
bool is_event_selected(Song::iterator event);
|
||||
void set_play_position(int pos);
|
||||
void invalidate();
|
||||
|
||||
void add_track();
|
||||
void new_pattern(const TrackCursor &cursor);
|
||||
void edit_pattern(const TrackEventRef &ref);
|
||||
void edit_pattern(Song::iterator event);
|
||||
void erase_events();
|
||||
|
||||
type_pattern_edit_request signal_pattern_edit_request();
|
||||
|
@ -143,13 +141,13 @@ public:
|
|||
protected:
|
||||
void invalidate_selection();
|
||||
void invalidate_play_position();
|
||||
void render_event(const TrackEventRef &ref);
|
||||
void render_track(Track &track);
|
||||
void render_event(Song::iterator event);
|
||||
void render_track(int track);
|
||||
void render_select_box();
|
||||
void invalidate_select_box();
|
||||
void select_from_box();
|
||||
|
||||
bool can_resize_event(const TrackEventRef &ref, int x);
|
||||
bool can_resize_event(Song::iterator event, int x);
|
||||
void get_drag_offset(int &frame, int &track);
|
||||
int get_step_size();
|
||||
int quantize_frame(int frame);
|
||||
|
@ -179,7 +177,7 @@ protected:
|
|||
Drag drag;
|
||||
|
||||
Model *model;
|
||||
EventSet selection;
|
||||
Song::IterList selection;
|
||||
|
||||
type_pattern_edit_request _pattern_edit_request;
|
||||
type_context_menu _signal_context_menu;
|
||||
|
|
Loading…
Reference in New Issue