MuseScore/mscore/editfiguredbass.cpp

170 lines
6 KiB
C++

//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2017 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include "musescore.h"
#include "scoreview.h"
#include "texttools.h"
#include "libmscore/chordrest.h"
#include "libmscore/figuredbass.h"
#include "libmscore/score.h"
#include "libmscore/segment.h"
#include "libmscore/measure.h"
namespace Ms {
//---------------------------------------------------------
// ScoreView::figuredBassEndEdit
// derived from harmonyEndEdit()
// remove the FB if empty
//---------------------------------------------------------
void ScoreView::figuredBassEndEdit()
{
FiguredBass* fb = static_cast<FiguredBass*>(editData.element);
if (fb->empty())
_score->undoRemoveElement(fb);
}
//---------------------------------------------------------
// ScoreView::figuredBassTab
// derived from harmonyTab() (for Harmony)
// manages [Space] / [Shift][Space] keys, moving editing to FB of next/prev ChordRest
// and [Tab] / [Shift][Tab] keys, moving to FB of next/prev measure
//---------------------------------------------------------
void ScoreView::figuredBassTab(bool bMeas, bool bBack)
{
FiguredBass* fb = (FiguredBass*)editData.element;
Segment* nextSegm;
Segment* segm = fb->segment();
int track = fb->track();
if (!segm) {
qDebug("figuredBassTab: no segment");
return;
}
// if moving to next/prev measure
if (bMeas) {
Measure* meas = segm->measure();
if (meas) {
if (bBack)
meas = meas->prevMeasure();
else
meas = meas->nextMeasure();
}
if (!meas) {
qDebug("figuredBassTab: no prev/next measure");
return;
}
// find initial ChordRest segment
nextSegm = meas->findSegment(SegmentType::ChordRest, meas->tick());
if (!nextSegm) {
qDebug("figuredBassTab: no ChordRest segment at measure");
return;
}
}
// if moving to next/prev chord segment
else {
// search next chord segment in same staff
nextSegm = bBack ? segm->prev1(SegmentType::ChordRest) : segm->next1(SegmentType::ChordRest);
int minTrack = (track / VOICES ) * VOICES;
int maxTrack = minTrack + (VOICES-1);
while (nextSegm) { // look for a ChordRest in the compatible track range
if(nextSegm->findAnnotationOrElement(ElementType::FIGURED_BASS, minTrack, maxTrack))
break;
nextSegm = bBack ? nextSegm->prev1(SegmentType::ChordRest) : nextSegm->next1(SegmentType::ChordRest);
}
if (!nextSegm) {
qDebug("figuredBassTab: no prev/next segment");
return;
}
}
changeState(ViewState::NORMAL);
_score->startCmd();
bool bNew;
// add a (new) FB element, using chord duration as default duration
FiguredBass * fbNew = FiguredBass::addFiguredBassToSegment(nextSegm, track, 0, &bNew);
if (bNew)
_score->undoAddElement(fbNew);
_score->select(fbNew, SelectType::SINGLE, 0);
startEdit(fbNew, Grip::NO_GRIP);
mscore->changeState(mscoreState());
adjustCanvasPosition(fbNew, false);
//TODO-edit ((FiguredBass*)editData.element)->moveCursorToEnd();
// _score->update(); // used by lyricsTab() but not by harmonyTab(): needed or not?
}
//---------------------------------------------------------
// figuredBassTicksTab
// manages [Ctrl] [1]-[9], extending current FB of the given number of ticks
//---------------------------------------------------------
void ScoreView::figuredBassTicksTab(int ticks)
{
FiguredBass* fb = toFiguredBass(editData.element);
int track = fb->track();
Segment* segm = fb->segment();
if (!segm) {
qDebug("figuredBassTicksTab: no segment");
return;
}
Measure* measure = segm->measure();
int nextSegTick = segm->tick() + ticks;
// find the measure containing the target tick
while (nextSegTick >= measure->tick() + measure->ticks()) {
measure = measure->nextMeasure();
if (!measure) {
qDebug("figuredBassTicksTab: no next measure");
return;
}
}
// look for a segment at this tick; if none, create one
Segment * nextSegm = segm;
while (nextSegm && nextSegm->tick() < nextSegTick)
nextSegm = nextSegm->next1(SegmentType::ChordRest);
if (!nextSegm || nextSegm->tick() > nextSegTick) { // no ChordRest segm at this tick
nextSegm = new Segment(measure, SegmentType::ChordRest, nextSegTick - measure->tick());
if (!nextSegm) {
qDebug("figuredBassTicksTab: no next segment");
return;
}
_score->undoAddElement(nextSegm);
}
changeState(ViewState::NORMAL);
_score->startCmd();
bool bNew;
FiguredBass * fbNew = FiguredBass::addFiguredBassToSegment(nextSegm, track, ticks, &bNew);
if (bNew)
_score->undoAddElement(fbNew);
_score->select(fbNew, SelectType::SINGLE, 0);
startEdit(fbNew, Grip::NO_GRIP);
mscore->changeState(mscoreState());
adjustCanvasPosition(fbNew, false);
//TODO-edit fb->moveCursorToEnd();
}
}