Implement cut/copy/paste/delete

This commit is contained in:
Matthias Neeracher 2007-01-02 07:09:06 +00:00
parent f2efc9408c
commit 11dab83982
4 changed files with 174 additions and 2 deletions

Binary file not shown.

View File

@ -792,8 +792,11 @@ void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop) const
}
}
VLSong::VLSong()
VLSong::VLSong(bool initialize)
{
if (!initialize)
return;
const VLFraction fourFour(4,4);
VLProperties defaultProperties = {fourFour, 0, 1, 3};
@ -1681,3 +1684,129 @@ void VLSong::iterator::AdjustStatus()
fStatus.push_back(Repeat(fMeasure, times));
}
}
VLSong VLSong::CopyMeasures(size_t beginMeasure, size_t endMeasure)
{
VLSong subSong(false);
int8_t firstProp = fMeasures[beginMeasure].fPropIdx;
int8_t lastProp = fMeasures[endMeasure-1].fPropIdx;
subSong.fProperties.insert(subSong.fProperties.end(),
fProperties.begin()+firstProp,
fProperties.begin()+lastProp+1);
subSong.fMeasures.insert(subSong.fMeasures.end(),
fMeasures.begin()+beginMeasure,
fMeasures.begin()+endMeasure);
if (firstProp)
for (size_t i=0; i<subSong.fMeasures.size(); ++i)
subSong.fMeasures[i].fPropIdx -= firstProp;
for (size_t r=0; r<fRepeats.size(); ++r)
if (fRepeats[r].fEndings[0].fBegin >= beginMeasure
&& fRepeats[r].fEndings[0].fEnd <= endMeasure
) {
VLRepeat repeat = fRepeats[r];
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
repeat.fEndings[e].fBegin -= beginMeasure;
repeat.fEndings[e].fEnd -= endMeasure;
}
subSong.fRepeats.push_back(repeat);
}
return subSong;
}
void VLSong::PasteMeasures(size_t beginMeasure, const VLSong & measures, int mode)
{
size_t numMeas = measures.CountMeasures();
size_t nextMeasure = mode==kInsert ? beginMeasure : beginMeasure+numMeas;
//
// Ignore properties for now. We don't use multiple properties yet.
//
if (mode == kInsert) {
fMeasures.insert(fMeasures.begin()+beginMeasure,
measures.fMeasures.begin(), measures.fMeasures.end());
for (size_t r=0; r<fRepeats.size(); ++r) {
VLRepeat & repeat = fRepeats[r];
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
if (repeat.fEndings[e].fBegin >= beginMeasure)
repeat.fEndings[e].fBegin += numMeas;
if (repeat.fEndings[e].fEnd >= beginMeasure)
repeat.fEndings[e].fEnd += numMeas;
}
}
for (size_t r=0; r<measures.fRepeats.size(); ++r) {
VLRepeat repeat = measures.fRepeats[r];
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
repeat.fEndings[e].fBegin += beginMeasure;
repeat.fEndings[e].fEnd += beginMeasure;
}
fRepeats.push_back(repeat);
}
} else {
if (CountMeasures() < nextMeasure) {
VLMeasure rest;
rest.fPropIdx = fMeasures.back().fPropIdx;
VLFraction dur = fProperties[rest.fPropIdx].fTime;
rest.fMelody.push_back(VLLyricsNote(VLRest(dur)));
VLChord rchord;
rchord.fDuration= dur;
rest.fChords.push_back(rchord);
fMeasures.insert(fMeasures.end(), nextMeasure-CountMeasures(), rest);
}
for (size_t m=0; m<numMeas; ++m) {
const VLMeasure & srcMeas = measures.fMeasures[m];
VLMeasure & dstMeas = fMeasures[beginMeasure+m];
if (mode & kOverwriteChords)
dstMeas.fChords = srcMeas.fChords;
if (mode & kOverwriteMelody)
dstMeas.fMelody = srcMeas.fMelody;
}
}
}
void VLSong::DeleteMeasures(size_t beginMeasure, size_t endMeasure)
{
int8_t firstProp = fMeasures[beginMeasure].fPropIdx;
int8_t lastProp = fMeasures[endMeasure-1].fPropIdx+1;
if (beginMeasure && fMeasures[beginMeasure-1].fPropIdx == firstProp)
++firstProp;
if (endMeasure < CountMeasures() && fMeasures[endMeasure].fPropIdx == lastProp)
--lastProp;
if (lastProp > firstProp) {
fProperties.erase(fProperties.begin()+firstProp,
fProperties.begin()+lastProp);
for (size_t m=endMeasure; m<CountMeasures(); ++m)
fMeasures[m].fPropIdx -= lastProp-firstProp;
}
fMeasures.erase(fMeasures.begin()+beginMeasure,
fMeasures.begin()+endMeasure);
size_t delta = endMeasure-beginMeasure;
for (size_t r=0; r<fRepeats.size(); ) {
VLRepeat & repeat = fRepeats[r];
if (repeat.fEndings[0].fBegin >= beginMeasure
&& repeat.fEndings[0].fEnd <= endMeasure
) {
fRepeats.erase(fRepeats.begin()+r);
} else {
for (size_t e=0; e<repeat.fEndings.size(); ) {
if (repeat.fEndings[e].fBegin > beginMeasure)
repeat.fEndings[e].fBegin =
std::max(beginMeasure, repeat.fEndings[e].fBegin-delta);
if (repeat.fEndings[e].fEnd > beginMeasure)
repeat.fEndings[e].fEnd =
std::max(beginMeasure, repeat.fEndings[e].fEnd-delta);
if (e && repeat.fEndings[e].fBegin==repeat.fEndings[e].fEnd)
repeat.fEndings.erase(repeat.fEndings.begin()+e);
else
++e;
}
++r;
}
}
}

View File

@ -219,6 +219,11 @@ struct VLProperties {
// Determine visual representation of note head
//
void VisualNote(VLFraction at, VLFraction actualDur, bool prevTriplet, VLFraction *visualDur, bool * triplet) const;
bool operator==(const VLProperties & other)
{ return fTime == other.fTime && fKey == other.fKey && fMode == other.fMode
&& fDivisions == other.fDivisions;
}
};
struct VLLyricsNote : VLNote {
@ -257,7 +262,7 @@ struct VLRepeat {
};
struct VLSong {
VLSong();
VLSong(bool initialize = true);
void swap(VLSong & other);
std::vector<VLProperties> fProperties;
@ -327,6 +332,16 @@ struct VLSong {
std::string GetWord(size_t stanza, size_t measure, VLFraction at);
void SetWord(size_t stanza, size_t measure, VLFraction at, std::string word);
enum {
kInsert,
kOverwriteChords = 1,
kOverwriteMelody = 2
};
VLSong CopyMeasures(size_t beginMeasure, size_t endMeasure);
void PasteMeasures(size_t beginMeasure, const VLSong & measures,
int mode = kInsert);
void DeleteMeasures(size_t beginMeasure, size_t endMeasure);
size_t CountMeasures() const { return fMeasures.size(); }
size_t CountStanzas() const;
void LilypondNotes(std::string & notes) const;

View File

@ -10,6 +10,11 @@
#import "VLSheetViewSelection.h"
#import "VLDocument.h"
//
// We're too lazy to properly serialize our private pasteboard format.
//
static VLSong sPasteboard;
@implementation VLSheetView (Selection)
- (void)editSelection
@ -74,18 +79,41 @@
- (IBAction)cut:(id)sender
{
[self copy:sender];
[self delete:sender];
}
- (IBAction)copy:(id)sender
{
NSPasteboard * pb = [NSPasteboard generalPasteboard];
NSString * pbType = [[NSBundle mainBundle] bundleIdentifier];
[pb declareTypes:[NSArray arrayWithObject:pbType] owner:nil];
if ([pb setString:@"whatever" forType:pbType])
sPasteboard = [self song]->CopyMeasures(fSelStart, fSelEnd);
}
- (IBAction)paste:(id)sender
{
NSPasteboard * pb = [NSPasteboard generalPasteboard];
NSString * pbType = [[NSBundle mainBundle] bundleIdentifier];
if ([pb availableTypeFromArray:[NSArray arrayWithObject:pbType]]) {
[[self document] willChangeSong];
if (![sender tag]) // Delete on paste, but not on overwrite
[self song]->DeleteMeasures(fSelStart, fSelEnd);
[self song]->PasteMeasures(fSelStart, sPasteboard, [sender tag]);
[[self document] didChangeSong];
[self setNeedsDisplay:YES];
}
}
- (IBAction)delete:(id)sender
{
[[self document] willChangeSong];
[self song]->DeleteMeasures(fSelStart, fSelEnd);
[[self document] didChangeSong];
[self setNeedsDisplay:YES];
}
- (IBAction)editRepeat:(id)sender