mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-23 03:34:00 +00:00
Rudimentary UI support for setting per-section properties
This commit is contained in:
parent
deb08552d7
commit
b8040292b1
|
@ -55,9 +55,9 @@ enum {
|
||||||
- (int) repeatVolta;
|
- (int) repeatVolta;
|
||||||
- (bool) brandNew;
|
- (bool) brandNew;
|
||||||
|
|
||||||
- (void) setKey:(int)key transpose:(BOOL)transpose;
|
- (void) setKey:(int)key transpose:(BOOL)transpose inSections:(NSRange)sections;
|
||||||
- (void) setTimeNum:(int)num denom:(int)denom;
|
- (void) setTimeNum:(int)num denom:(int)denom inSections:(NSRange)sections;
|
||||||
- (void) setDivisions:(int)divisions;
|
- (void) setDivisions:(int)divisions inSections:(NSRange)sections;
|
||||||
- (void) setRepeatVolta:(int)repeatVolta;
|
- (void) setRepeatVolta:(int)repeatVolta;
|
||||||
|
|
||||||
- (IBAction) showOutput:(id)sender;
|
- (IBAction) showOutput:(id)sender;
|
||||||
|
|
|
@ -203,11 +203,12 @@
|
||||||
return [NSNumber numberWithInt: (prop.fKey << 8) | (prop.fMode & 0xFF)];
|
return [NSNumber numberWithInt: (prop.fKey << 8) | (prop.fMode & 0xFF)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setKey:(int)key transpose:(BOOL)transpose
|
- (void) setKey:(int)key transpose:(BOOL)transpose inSections:(NSRange)sections
|
||||||
{
|
{
|
||||||
[self willChangeSong];
|
[self willChangeSong];
|
||||||
[self willChangeValueForKey:@"songKey"];
|
[self willChangeValueForKey:@"songKey"];
|
||||||
song->ChangeKey(key>>8, key & 0xFF, transpose);
|
while (sections.length-- > 0)
|
||||||
|
song->ChangeKey(sections.location++, key>>8, key & 0xFF, transpose);
|
||||||
[self didChangeValueForKey:@"songKey"];
|
[self didChangeValueForKey:@"songKey"];
|
||||||
[self didChangeSong];
|
[self didChangeSong];
|
||||||
}
|
}
|
||||||
|
@ -219,11 +220,12 @@
|
||||||
return [NSNumber numberWithInt: (prop.fTime.fNum << 8) | prop.fTime.fDenom];
|
return [NSNumber numberWithInt: (prop.fTime.fNum << 8) | prop.fTime.fDenom];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setTimeNum:(int)num denom:(int)denom
|
- (void) setTimeNum:(int)num denom:(int)denom inSections:(NSRange)sections
|
||||||
{
|
{
|
||||||
[self willChangeSong];
|
[self willChangeSong];
|
||||||
[self willChangeValueForKey:@"songTime"];
|
[self willChangeValueForKey:@"songTime"];
|
||||||
song->ChangeTime(VLFraction(num, denom));
|
while (sections.length-- > 0)
|
||||||
|
song->ChangeTime(sections.location++, VLFraction(num, denom));
|
||||||
[self didChangeValueForKey:@"songTime"];
|
[self didChangeValueForKey:@"songTime"];
|
||||||
[self didChangeSong];
|
[self didChangeSong];
|
||||||
}
|
}
|
||||||
|
@ -235,12 +237,13 @@
|
||||||
return [NSNumber numberWithInt: prop.fDivisions];
|
return [NSNumber numberWithInt: prop.fDivisions];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setDivisions:(int)divisions
|
- (void) setDivisions:(int)divisions inSections:(NSRange)sections
|
||||||
{
|
{
|
||||||
[self willChangeSong];
|
[self willChangeSong];
|
||||||
[self willChangeValueForKey:@"songDivisions"];
|
[self willChangeValueForKey:@"songDivisions"];
|
||||||
[self willChangeSong];
|
[self willChangeSong];
|
||||||
song->ChangeDivisions(divisions);
|
while (sections.length-- > 0)
|
||||||
|
song->ChangeDivisions(sections.location++, divisions);
|
||||||
[self didChangeValueForKey:@"songDivisions"];
|
[self didChangeValueForKey:@"songDivisions"];
|
||||||
[self didChangeSong];
|
[self didChangeSong];
|
||||||
}
|
}
|
||||||
|
|
|
@ -896,9 +896,9 @@ static void TransposePinned(int8_t & pitch, int semi)
|
||||||
pitch = octave+pitchInOctave;
|
pitch = octave+pitchInOctave;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::ChangeKey(int newKey, int newMode, bool transpose)
|
void VLSong::ChangeKey(int section, int newKey, int newMode, bool transpose)
|
||||||
{
|
{
|
||||||
VLProperties & prop = fProperties.front();
|
VLProperties & prop = fProperties[section];
|
||||||
int semi = 7*(newKey-prop.fKey) % 12;
|
int semi = 7*(newKey-prop.fKey) % 12;
|
||||||
prop.fKey = newKey;
|
prop.fKey = newKey;
|
||||||
prop.fMode = newMode;
|
prop.fMode = newMode;
|
||||||
|
@ -906,6 +906,9 @@ void VLSong::ChangeKey(int newKey, int newMode, bool transpose)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
||||||
|
if (fMeasures[measure].fPropIdx != section)
|
||||||
|
continue;
|
||||||
|
|
||||||
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
||||||
VLChordList::iterator e = fMeasures[measure].fChords.end();
|
VLChordList::iterator e = fMeasures[measure].fChords.end();
|
||||||
|
|
||||||
|
@ -918,6 +921,9 @@ void VLSong::ChangeKey(int newKey, int newMode, bool transpose)
|
||||||
int8_t low = 127;
|
int8_t low = 127;
|
||||||
int8_t high = 0;
|
int8_t high = 0;
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
||||||
|
if (fMeasures[measure].fPropIdx != section)
|
||||||
|
continue;
|
||||||
|
|
||||||
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
||||||
VLNoteList::iterator e = fMeasures[measure].fMelody.end();
|
VLNoteList::iterator e = fMeasures[measure].fMelody.end();
|
||||||
|
|
||||||
|
@ -1026,101 +1032,137 @@ VLFraction VLRealigner::operator()(VLFraction at)
|
||||||
return quarters + fTable[at.fNum / at.fDenom]*fNewFrac;
|
return quarters + fTable[at.fNum / at.fDenom]*fNewFrac;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::ChangeDivisions(int newDivisions)
|
static VLChordList Realign(const VLChordList & chords,
|
||||||
|
const VLProperties& fromProp,
|
||||||
|
const VLProperties& toProp)
|
||||||
{
|
{
|
||||||
VLProperties & prop = fProperties.front();
|
if (fromProp.fTime == toProp.fTime)
|
||||||
if (newDivisions == prop.fDivisions)
|
return chords;
|
||||||
return; // Unchanged
|
if (fromProp.fTime < toProp.fTime) {
|
||||||
|
VLChord rchord(toProp.fTime-fromProp.fTime);
|
||||||
|
VLChordList newChords(chords);
|
||||||
|
newChords.push_back(rchord);
|
||||||
|
|
||||||
VLRealigner realign(prop.fDivisions, newDivisions);
|
return newChords;
|
||||||
//
|
} else {
|
||||||
// Only melody needs to be realigned, chords are already quarter notes
|
VLChordList::const_iterator i = chords.begin();
|
||||||
//
|
VLChordList::const_iterator e = chords.end();
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
VLFraction at(0);
|
||||||
VLNoteList newMelody;
|
VLChordList newChords;
|
||||||
|
|
||||||
|
for (; i!=e; ++i) {
|
||||||
|
VLChord c = *i;
|
||||||
|
if (at+c.fDuration >= toProp.fTime) {
|
||||||
|
if (at < toProp.fTime) {
|
||||||
|
c.fDuration = toProp.fTime-at;
|
||||||
|
newChords.push_back(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newChords.push_back(c);
|
||||||
|
at += c.fDuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newChords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VLNoteList Realign(const VLNoteList & notes,
|
||||||
|
const VLProperties& fromProp,
|
||||||
|
const VLProperties& toProp)
|
||||||
|
{
|
||||||
|
if (fromProp.fTime == toProp.fTime && fromProp.fDivisions == toProp.fDivisions)
|
||||||
|
return notes;
|
||||||
|
VLNoteList newNotes(notes);
|
||||||
|
if (fromProp.fTime < toProp.fTime) {
|
||||||
|
VLNote rest(toProp.fTime-fromProp.fTime);
|
||||||
|
newNotes.push_back(rest);
|
||||||
|
} else if (fromProp.fTime > toProp.fTime) {
|
||||||
|
VLNoteList::const_iterator i = notes.begin();
|
||||||
|
VLNoteList::const_iterator e = notes.end();
|
||||||
|
VLFraction at(0);
|
||||||
|
|
||||||
|
for (; i!=e; ++i) {
|
||||||
|
VLNote n = *i;
|
||||||
|
if (at+n.fDuration >= toProp.fTime) {
|
||||||
|
if (at < toProp.fTime) {
|
||||||
|
n.fDuration = toProp.fTime-at;
|
||||||
|
newNotes.push_back(n);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newNotes.push_back(n);
|
||||||
|
at += n.fDuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fromProp.fDivisions == toProp.fDivisions) {
|
||||||
|
VLRealigner realign(fromProp.fDivisions, toProp.fDivisions);
|
||||||
|
|
||||||
|
VLNoteList alignedNotes;
|
||||||
VLFraction at(0);
|
VLFraction at(0);
|
||||||
VLFraction lastAt;
|
VLFraction lastAt;
|
||||||
|
|
||||||
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
VLNoteList::iterator i = newNotes.begin();
|
||||||
VLNoteList::iterator e = fMeasures[measure].fMelody.end();
|
VLNoteList::iterator e = newNotes.end();
|
||||||
|
|
||||||
for (; i!=e; ++i) {
|
for (; i!=e; ++i) {
|
||||||
VLLyricsNote n = *i;
|
VLLyricsNote n = *i;
|
||||||
VLFraction newAt = realign(at);
|
VLFraction newAt = realign(at);
|
||||||
if (newMelody.empty()) {
|
if (alignedNotes.empty()) {
|
||||||
newMelody.push_back(n);
|
alignedNotes.push_back(n);
|
||||||
lastAt = newAt;
|
lastAt = newAt;
|
||||||
} else if (newAt != lastAt) {
|
} else if (newAt != lastAt) {
|
||||||
newMelody.back().fDuration = newAt-lastAt;
|
alignedNotes.back().fDuration = newAt-lastAt;
|
||||||
newMelody.push_back(n);
|
alignedNotes.push_back(n);
|
||||||
lastAt = newAt;
|
lastAt = newAt;
|
||||||
}
|
}
|
||||||
at += n.fDuration;
|
at += n.fDuration;
|
||||||
}
|
}
|
||||||
if (lastAt == at)
|
if (lastAt == at)
|
||||||
newMelody.pop_back();
|
alignedNotes.pop_back();
|
||||||
else
|
else
|
||||||
newMelody.back().fDuration = at-lastAt;
|
alignedNotes.back().fDuration = at-lastAt;
|
||||||
fMeasures[measure].fMelody.swap(newMelody);
|
|
||||||
}
|
return alignedNotes;
|
||||||
prop.fDivisions = newDivisions;
|
} else
|
||||||
|
return newNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::ChangeTime(VLFraction newTime)
|
void VLSong::ChangeDivisions(int section, int newDivisions)
|
||||||
{
|
{
|
||||||
VLProperties & prop = fProperties.front();
|
VLProperties & prop = fProperties[section];
|
||||||
|
if (prop.fDivisions == newDivisions)
|
||||||
|
return; // Unchanged
|
||||||
|
VLProperties newProp = prop;
|
||||||
|
newProp.fDivisions = newDivisions;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Only melody needs to be realigned, chords are already quarter notes
|
||||||
|
//
|
||||||
|
for (size_t measure=0; measure<fMeasures.size(); ++measure)
|
||||||
|
if (fMeasures[measure].fPropIdx == section)
|
||||||
|
fMeasures[measure].fMelody =
|
||||||
|
Realign(fMeasures[measure].fMelody, prop, newProp);
|
||||||
|
prop = newProp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VLSong::ChangeTime(int section, VLFraction newTime)
|
||||||
|
{
|
||||||
|
VLProperties & prop = fProperties[section];
|
||||||
if (prop.fTime == newTime)
|
if (prop.fTime == newTime)
|
||||||
return; // No change
|
return; // No change
|
||||||
VLChord rchord(newTime-prop.fTime);
|
VLProperties newProp = prop;
|
||||||
VLLyricsNote rnote(newTime-prop.fTime);
|
newProp.fTime = newTime;
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure)
|
||||||
if (newTime < prop.fTime) {
|
if (fMeasures[measure].fPropIdx == section) {
|
||||||
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
fMeasures[measure].fChords =
|
||||||
VLChordList::iterator e = fMeasures[measure].fChords.end();
|
Realign(fMeasures[measure].fChords, prop, newProp);
|
||||||
VLFraction at(0);
|
fMeasures[measure].fMelody =
|
||||||
VLChordList newChords;
|
Realign(fMeasures[measure].fMelody, prop, newProp);
|
||||||
|
}
|
||||||
for (; i!=e; ++i) {
|
prop = newProp;
|
||||||
VLChord c = *i;
|
|
||||||
if (at+c.fDuration >= newTime) {
|
|
||||||
if (at < newTime) {
|
|
||||||
c.fDuration = newTime-at;
|
|
||||||
newChords.push_back(c);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
newChords.push_back(c);
|
|
||||||
at += c.fDuration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fMeasures[measure].fChords.swap(newChords);
|
|
||||||
} else
|
|
||||||
fMeasures[measure].fChords.push_back(rchord);
|
|
||||||
|
|
||||||
if (newTime < prop.fTime) {
|
|
||||||
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
|
||||||
VLNoteList::iterator e = fMeasures[measure].fMelody.end();
|
|
||||||
VLFraction at(0);
|
|
||||||
VLNoteList newMelody;
|
|
||||||
|
|
||||||
for (; i!=e; ++i) {
|
|
||||||
VLLyricsNote n = *i;
|
|
||||||
if (at+n.fDuration >= newTime) {
|
|
||||||
if (at < newTime) {
|
|
||||||
n.fDuration = newTime-at;
|
|
||||||
newMelody.push_back(n);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
newMelody.push_back(n);
|
|
||||||
at += n.fDuration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fMeasures[measure].fMelody.swap(newMelody);
|
|
||||||
} else
|
|
||||||
fMeasures[measure].fMelody.push_back(rnote);
|
|
||||||
}
|
|
||||||
prop.fTime = newTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t VLSong::EmptyEnding() const
|
size_t VLSong::EmptyEnding() const
|
||||||
|
@ -1867,12 +1909,34 @@ void VLSong::PasteMeasures(size_t beginMeasure, const VLSong & measures, int mod
|
||||||
{
|
{
|
||||||
size_t numMeas = measures.CountMeasures();
|
size_t numMeas = measures.CountMeasures();
|
||||||
size_t nextMeasure = mode==kInsert ? beginMeasure : beginMeasure+numMeas;
|
size_t nextMeasure = mode==kInsert ? beginMeasure : beginMeasure+numMeas;
|
||||||
//
|
|
||||||
// Ignore properties for now. We don't use multiple properties yet.
|
|
||||||
//
|
|
||||||
if (mode == kInsert) {
|
if (mode == kInsert) {
|
||||||
|
int propAt = fMeasures[beginMeasure].fPropIdx;
|
||||||
|
int propOffset = 0;
|
||||||
|
VLPropertyList::const_iterator beginProp = measures.fProperties.begin();
|
||||||
|
VLPropertyList::const_iterator endProp = measures.fProperties.end();
|
||||||
|
|
||||||
|
if (beginMeasure) {
|
||||||
|
propOffset = fMeasures[beginMeasure-1].fPropIdx;
|
||||||
|
if (fProperties[propOffset] == beginProp[0])
|
||||||
|
++beginProp;
|
||||||
|
else
|
||||||
|
++propOffset;
|
||||||
|
if (fProperties[propAt] == endProp[-1])
|
||||||
|
--endProp;
|
||||||
|
}
|
||||||
|
int postOffset = endProp - beginProp;
|
||||||
|
|
||||||
|
fProperties.insert(fProperties.begin()+propAt, beginProp, endProp);
|
||||||
fMeasures.insert(fMeasures.begin()+beginMeasure,
|
fMeasures.insert(fMeasures.begin()+beginMeasure,
|
||||||
measures.fMeasures.begin(), measures.fMeasures.end());
|
measures.fMeasures.begin(), measures.fMeasures.end());
|
||||||
|
if (propOffset)
|
||||||
|
for (size_t meas=beginMeasure; meas<beginMeasure+numMeas; ++meas)
|
||||||
|
fMeasures[meas].fPropIdx += propOffset;
|
||||||
|
if (postOffset)
|
||||||
|
for (size_t meas=beginMeasure+numMeas; meas<fMeasures.size(); ++meas)
|
||||||
|
fMeasures[meas].fPropIdx += postOffset;
|
||||||
|
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r) {
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
VLRepeat & repeat = fRepeats[r];
|
VLRepeat & repeat = fRepeats[r];
|
||||||
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
|
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
|
||||||
|
@ -1904,9 +1968,13 @@ void VLSong::PasteMeasures(size_t beginMeasure, const VLSong & measures, int mod
|
||||||
const VLMeasure & srcMeas = measures.fMeasures[m];
|
const VLMeasure & srcMeas = measures.fMeasures[m];
|
||||||
VLMeasure & dstMeas = fMeasures[beginMeasure+m];
|
VLMeasure & dstMeas = fMeasures[beginMeasure+m];
|
||||||
if (mode & kOverwriteChords)
|
if (mode & kOverwriteChords)
|
||||||
dstMeas.fChords = srcMeas.fChords;
|
dstMeas.fChords = Realign(srcMeas.fChords,
|
||||||
|
measures.fProperties[srcMeas.fPropIdx],
|
||||||
|
fProperties[dstMeas.fPropIdx]);
|
||||||
if (mode & kOverwriteMelody)
|
if (mode & kOverwriteMelody)
|
||||||
dstMeas.fMelody = srcMeas.fMelody;
|
dstMeas.fMelody = Realign(srcMeas.fMelody,
|
||||||
|
measures.fProperties[srcMeas.fPropIdx],
|
||||||
|
fProperties[dstMeas.fPropIdx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,17 +269,21 @@ struct VLRepeat {
|
||||||
std::vector<Ending> fEndings;
|
std::vector<Ending> fEndings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<VLProperties> VLPropertyList;
|
||||||
|
typedef std::vector<VLMeasure> VLMeasureList;
|
||||||
|
typedef std::vector<VLRepeat> VLRepeatList;
|
||||||
|
|
||||||
class VLSong {
|
class VLSong {
|
||||||
public:
|
public:
|
||||||
VLSong(bool initialize = true);
|
VLSong(bool initialize = true);
|
||||||
void swap(VLSong & other);
|
void swap(VLSong & other);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
std::vector<VLProperties> fProperties;
|
VLPropertyList fProperties;
|
||||||
std::vector<VLMeasure> fMeasures;
|
VLMeasureList fMeasures;
|
||||||
std::vector<VLRepeat> fRepeats;
|
VLRepeatList fRepeats;
|
||||||
int8_t fGoToCoda;
|
int8_t fGoToCoda;
|
||||||
int8_t fCoda;
|
int8_t fCoda;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Iterate over measures in performance order
|
// Iterate over measures in performance order
|
||||||
|
@ -340,9 +344,9 @@ public:
|
||||||
bool DoesTieWithPrevRepeat(size_t measure) const;
|
bool DoesTieWithPrevRepeat(size_t measure) const;
|
||||||
bool DoesTieWithNextRepeat(size_t measure) const;
|
bool DoesTieWithNextRepeat(size_t measure) const;
|
||||||
bool IsNonEmpty() const;
|
bool IsNonEmpty() const;
|
||||||
void ChangeKey(int newKey, int newMode, bool transpose);
|
void ChangeKey(int section, int newKey, int newMode, bool transpose);
|
||||||
void ChangeDivisions(int newDivisions);
|
void ChangeDivisions(int section, int newDivisions);
|
||||||
void ChangeTime(VLFraction newTime);
|
void ChangeTime(int section, VLFraction newTime);
|
||||||
|
|
||||||
bool FindWord(size_t stanza, size_t & measure, VLFraction & at);
|
bool FindWord(size_t stanza, size_t & measure, VLFraction & at);
|
||||||
bool PrevWord(size_t stanza, size_t & measure, VLFraction & at);
|
bool PrevWord(size_t stanza, size_t & measure, VLFraction & at);
|
||||||
|
|
|
@ -591,7 +591,8 @@ const char * sBreak[3] = {"", "\xE2\xA4\xBE", "\xE2\x8E\x98"};
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int key = [[sender selectedItem] tag];
|
int key = [[sender selectedItem] tag];
|
||||||
[[self document] setKey:key transpose:returnCode==NSAlertDefaultReturn];
|
[[self document] setKey:key transpose:returnCode==NSAlertDefaultReturn
|
||||||
|
inSections:[self sectionsInSelection]];
|
||||||
fNeedsRecalc = kRecalc;
|
fNeedsRecalc = kRecalc;
|
||||||
[self setNeedsDisplay: YES];
|
[self setNeedsDisplay: YES];
|
||||||
}
|
}
|
||||||
|
@ -617,7 +618,8 @@ const char * sBreak[3] = {"", "\xE2\xA4\xBE", "\xE2\x8E\x98"};
|
||||||
{
|
{
|
||||||
int time = [[sender selectedItem] tag];
|
int time = [[sender selectedItem] tag];
|
||||||
|
|
||||||
[[self document] setTimeNum: time >> 8 denom: time & 0xFF];
|
[[self document] setTimeNum: time >> 8 denom: time & 0xFF
|
||||||
|
inSections:[self sectionsInSelection]];
|
||||||
fNeedsRecalc = kRecalc;
|
fNeedsRecalc = kRecalc;
|
||||||
[self setNeedsDisplay: YES];
|
[self setNeedsDisplay: YES];
|
||||||
}
|
}
|
||||||
|
@ -626,7 +628,7 @@ const char * sBreak[3] = {"", "\xE2\xA4\xBE", "\xE2\x8E\x98"};
|
||||||
{
|
{
|
||||||
int div = [[sender selectedItem] tag];
|
int div = [[sender selectedItem] tag];
|
||||||
|
|
||||||
[[self document] setDivisions: div];
|
[[self document] setDivisions: div inSections:[self sectionsInSelection]];
|
||||||
fNeedsRecalc = kRecalc;
|
fNeedsRecalc = kRecalc;
|
||||||
[self setNeedsDisplay: YES];
|
[self setNeedsDisplay: YES];
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
- (void)editSelection;
|
- (void)editSelection;
|
||||||
- (void)adjustSelection:(NSEvent *)event;
|
- (void)adjustSelection:(NSEvent *)event;
|
||||||
|
- (NSRange)sectionsInSelection;
|
||||||
|
|
||||||
- (BOOL)validateUserInterfaceItem:(id)item;
|
- (BOOL)validateUserInterfaceItem:(id)item;
|
||||||
- (IBAction)cut:(id)sender;
|
- (IBAction)cut:(id)sender;
|
||||||
|
|
|
@ -61,6 +61,27 @@ static VLSong sPasteboard;
|
||||||
fCursorRegion = kRegionMeasure;
|
fCursorRegion = kRegionMeasure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSRange)sectionsInSelection
|
||||||
|
{
|
||||||
|
NSRange sections;
|
||||||
|
int firstSection;
|
||||||
|
int lastSection;
|
||||||
|
VLSong * song = [self song];
|
||||||
|
|
||||||
|
if (fSelEnd > -1) {
|
||||||
|
firstSection = song->fMeasures[fSelStart].fPropIdx;
|
||||||
|
lastSection = fSelEnd > fSelStart+1 ?
|
||||||
|
song->fMeasures[fSelEnd].fPropIdx : firstSection;
|
||||||
|
} else {
|
||||||
|
firstSection = 0;
|
||||||
|
lastSection = song->fMeasures.back().fPropIdx;
|
||||||
|
}
|
||||||
|
sections.location = firstSection;
|
||||||
|
sections.length = lastSection-firstSection+1;
|
||||||
|
|
||||||
|
return sections;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)validateMenuItem:(id) item
|
- (BOOL)validateMenuItem:(id) item
|
||||||
{
|
{
|
||||||
SEL action = [item action];
|
SEL action = [item action];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user