void System::layout(qreal xo1) { if (isVbox()) // ignore vbox return; static const Spatium instrumentNameOffset(1.0); int nstaves = _staves.size(); if (nstaves != score()->nstaves()) qDebug("System::layout: nstaves %d != %d", nstaves, score()->nstaves()); //--------------------------------------------------- // find x position of staves // create brackets //--------------------------------------------------- qreal xoff2 = 0.0; // x offset for instrument name int bracketLevels = 0; for (int idx = 0; idx < nstaves; ++idx) bracketLevels = qMax(bracketLevels, score()->staff(idx)->bracketLevels()); qreal bracketWidth[bracketLevels]; for (int i = 0; i < bracketLevels; ++i) bracketWidth[i] = 0.0; QList<Bracket*> bl = _brackets; _brackets.clear(); for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { Staff* s = score()->staff(staffIdx); for (int i = 0; i < bracketLevels; ++i) { if (s->bracket(i) == BracketType::NO_BRACKET) continue; int firstStaff = staffIdx; int lastStaff = staffIdx + s->bracketSpan(i) - 1; if (lastStaff >= nstaves) lastStaff = nstaves - 1; for (; firstStaff <= lastStaff; ++firstStaff) { if (score()->staff(firstStaff)->show()) break; } for (; lastStaff >= firstStaff; --lastStaff) { if (score()->staff(lastStaff)->show()) break; } int span = lastStaff - firstStaff + 1; // // do not show bracket if it only spans one // system due to some invisible staves // if ((span > 1) || (s->bracketSpan(i) == span)) { // // this bracket is visible // Bracket* b = 0; int track = staffIdx * VOICES; for (int k = 0; k < bl.size(); ++k) { if (bl[k]->track() == track && bl[k]->level() == i) { b = bl.takeAt(k); break; } } if (b == 0) { b = new Bracket(score()); b->setGenerated(true); b->setParent(this); b->setTrack(track); b->setLevel(i); b->setBracketType(s->bracket(i)); b->setSpan(s->bracketSpan(i)); score()->undoAddElement(b); } else _brackets.append(b); b->setFirstStaff(firstStaff); b->setLastStaff(lastStaff); bracketWidth[i] = qMax(bracketWidth[i], b->width()); } } if (!s->show()) continue; for (InstrumentName* t : _staves[staffIdx]->instrumentNames) { t->layout(); qreal w = t->width() + point(instrumentNameOffset); if (w > xoff2) xoff2 = w; } } for (Bracket* b : bl) score()->undoRemoveElement(b); //--------------------------------------------------- // layout SysStaff and StaffLines //--------------------------------------------------- // xoff2 += xo1; _leftMargin = xoff2; qreal bd = point(score()->styleS(StyleIdx::bracketDistance)); if ( _brackets.size() > 0) { for (int i = 0; i < bracketLevels; ++i) _leftMargin += bracketWidth[i] + bd; } for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) { SysStaff* s = _staves[staffIdx]; Staff* staff = score()->staff(staffIdx); if (!staff->show() || !s->show()) { s->setbbox(QRectF()); continue; } qreal staffMag = staff->mag(); qreal h; if (staff->lines() == 1) h = 2; else h = (staff->lines()-1) * staff->lineDistance(); h = h * staffMag * spatium(); s->bbox().setRect(_leftMargin + xo1, 0.0, 0.0, h); } if ((nstaves > 1 && score()->styleB(StyleIdx::startBarlineMultiple)) || (nstaves <= 1 && score()->styleB(StyleIdx::startBarlineSingle))) { if (_barLine == 0) { BarLine* bl = new BarLine(score()); bl->setParent(this); bl->setTrack(0); bl->setGenerated(true); score()->undoAddElement(bl); } } else if (_barLine) score()->undoRemoveElement(_barLine); if (_barLine) _barLine->rxpos() = _leftMargin + xo1; //--------------------------------------------------- // layout brackets //--------------------------------------------------- for (Bracket* b : _brackets) { qreal xo = -xo1; for (const Bracket* b2 : _brackets) { if (b->level() > b2->level() && ((b->firstStaff() >= b2->firstStaff() && b->firstStaff() <= b2->lastStaff()) || (b->lastStaff() >= b2->firstStaff() && b->lastStaff() <= b2->lastStaff()))) xo += b2->width() + bd; } b->rxpos() = _leftMargin - xo - b->width(); } //--------------------------------------------------- // layout instrument names x position //--------------------------------------------------- int idx = 0; for (const Part* p : score()->parts()) { SysStaff* s = staff(idx); if (s->show() && p->show()) { for (InstrumentName* t : s->instrumentNames) { switch (t->textStyle().align() & AlignmentFlags::HMASK) { case int(AlignmentFlags::LEFT): t->rxpos() = 0; break; case int(AlignmentFlags::HCENTER): t->rxpos() = (xoff2 - point(instrumentNameOffset) + xo1) * .5; break; case int(AlignmentFlags::RIGHT): default: t->rxpos() = xoff2 - point(instrumentNameOffset) + xo1; break; } t->rxpos() += t->textStyle().offset(t->spatium()).x(); } } idx += p->nstaves(); } }
Element* ChordRest::drop(const DropData& data) { Element* e = data.element; Measure* m = measure(); switch (e->type()) { case Element::Type::BREATH: { Breath* b = static_cast<Breath*>(e); b->setTrack(staffIdx() * VOICES); // TODO: insert automatically in all staves? Segment* seg = m->undoGetSegment(Segment::Type::Breath, tick()); b->setParent(seg); score()->undoAddElement(b); } return e; case Element::Type::BAR_LINE: { BarLine* bl = static_cast<BarLine*>(e); bl->setTrack(staffIdx() * VOICES); if (tick() == m->tick()) return m->drop(data); Segment* seg = m->undoGetSegment(Segment::Type::BarLine, tick()); bl->setParent(seg); score()->undoAddElement(bl); } return e; case Element::Type::CLEF: score()->cmdInsertClef(static_cast<Clef*>(e), this); break; case Element::Type::TEMPO_TEXT: { TempoText* tt = static_cast<TempoText*>(e); tt->setParent(segment()); TextStyleType st = tt->textStyleType(); tt->setTextStyleType(st); score()->undoAddElement(tt); } return e; case Element::Type::DYNAMIC: { Dynamic* d = static_cast<Dynamic*>(e); d->setTrack(track()); TextStyleType st = d->textStyleType(); d->setTextStyleType(st); d->setParent(segment()); score()->undoAddElement(d); } return e; case Element::Type::FRET_DIAGRAM: case Element::Type::SYMBOL: e->setTrack(track()); e->setParent(segment()); score()->undoAddElement(e); return e; case Element::Type::NOTE: { Note* note = static_cast<Note*>(e); NoteVal nval; nval.pitch = note->pitch(); nval.headGroup = note->headGroup(); nval.fret = note->fret(); nval.string = note->string(); score()->setNoteRest(segment(), track(), nval, data.duration, MScore::Direction::AUTO); delete e; } break; case Element::Type::HARMONY: static_cast<Harmony*>(e)->render(); // fall through case Element::Type::TEXT: case Element::Type::STAFF_TEXT: case Element::Type::STAFF_STATE: case Element::Type::INSTRUMENT_CHANGE: case Element::Type::REHEARSAL_MARK: e->setParent(segment()); e->setTrack((track() / VOICES) * VOICES); { Text* f = static_cast<Text*>(e); TextStyleType st = f->textStyleType(); if (st >= TextStyleType::DEFAULT) f->setTextStyleType(st); } score()->undoAddElement(e); return e; case Element::Type::FIGURED_BASS: { bool bNew; FiguredBass * fb = static_cast<FiguredBass *>(e); fb->setParent( segment() ); fb->setTrack( (track() / VOICES) * VOICES ); fb->setTicks( duration().ticks() ); fb->setOnNote(true); FiguredBass::addFiguredBassToSegment(segment(), fb->track(), fb->ticks(), &bNew); if (bNew) score()->undoAddElement(e); return e; } case Element::Type::IMAGE: e->setParent(segment()); score()->undoAddElement(e); return e; case Element::Type::ICON: { switch(static_cast<Icon*>(e)->iconType()) { case IconType::SBEAM: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::BEGIN)); break; case IconType::MBEAM: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::MID)); break; case IconType::NBEAM: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::NONE)); break; case IconType::BEAM32: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::BEGIN32)); break; case IconType::BEAM64: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::BEGIN64)); break; case IconType::AUTOBEAM: score()->undoChangeProperty(this, P_ID::BEAM_MODE, int(Beam::Mode::AUTO)); break; default: break; } } delete e; break; default: qDebug("cannot drop %s", e->name()); delete e; return 0; } return 0; }
void ContinuousPanel::draw(QPainter& painter, const QList<Element*>& el) { painter.save(); painter.setRenderHint(QPainter::Antialiasing, preferences.antialiasedDrawing); painter.setRenderHint(QPainter::TextAntialiasing, true); // Draw colored rectangle painter.setClipping(false); QPointF pos(_offsetPanel, 0); painter.translate(pos); QPen pen; pen.setWidthF(0.0); pen.setStyle(Qt::NoPen); painter.setPen(pen); painter.setBrush(preferences.fgColor); QRectF bg(_rect); bg.setWidth(_widthClef + _widthKeySig + _widthTimeSig + _leftMarginTotal + _panelRightPadding); QPixmap* fgPixmap = _sv->fgPixmap(); if (fgPixmap == 0 || fgPixmap->isNull()) painter.fillRect(bg, preferences.fgColor); else { painter.setMatrixEnabled(false); painter.drawTiledPixmap(bg, *fgPixmap, bg.topLeft() - QPoint(lrint(_sv->matrix().dx()), lrint(_sv->matrix().dy()))); painter.setMatrixEnabled(true); } painter.setClipRect(_rect); painter.setClipping(true); QColor color(MScore::layoutBreakColor); // Draw measure text number QString text = _mmRestCount ? QString("#%1-%2").arg(_currentMeasureNo+1).arg(_currentMeasureNo+_mmRestCount) : QString("#%1").arg(_currentMeasureNo+1); Text* newElement = new Text(_score); newElement->setTextStyleType(TextStyleType::DEFAULT); newElement->setFlag(ElementFlag::MOVABLE, false); newElement->setXmlText(text); newElement->textStyle().setFamily("FreeSans"); newElement->textStyle().setSizeIsSpatiumDependent(true); newElement->setColor(color); newElement->sameLayout(); pos = QPointF(_score->styleP(StyleIdx::clefLeftMargin) + _widthClef, _y + newElement->height()); painter.translate(pos); newElement->draw(&painter); pos += QPointF(_offsetPanel, 0); painter.translate(-pos); delete newElement; // This second pass draws the elements spaced evently using the width of the largest element for (const Element* e : el) { e->itemDiscovered = 0; if (!e->visible()) { if (_score->printing() || !_score->showInvisible()) continue; } if (e->type() == Element::Type::STAFF_LINES) { Staff* currentStaff = _score->staff(e->staffIdx()); Segment* parent = _score->tick2segmentMM(_currentMeasureTick); pos = QPointF (_offsetPanel, e->pagePos().y()); painter.translate(pos); // Draw staff lines StaffLines* newStaffLines = static_cast<StaffLines*>(e->clone()); newStaffLines->setWidth(bg.width()); newStaffLines->setParent(parent); newStaffLines->setTrack(e->track()); newStaffLines->layout(); newStaffLines->setColor(color); newStaffLines->draw(&painter); delete newStaffLines; // Draw barline BarLine* newBarLine = new BarLine(_score); newBarLine->setBarLineType(BarLineType::NORMAL); newBarLine->setParent(parent); newBarLine->setTrack(e->track()); newBarLine->setSpan(currentStaff->barLineSpan()); newBarLine->setSpanFrom(currentStaff->barLineFrom()); newBarLine->setSpanTo(currentStaff->barLineTo()); newBarLine->layout(); newBarLine->setColor(color); newBarLine->draw(&painter); delete newBarLine; // Draw the current staff name QList<StaffName>& staffNamesLong = currentStaff->part()->instrument()->longNames(); QString staffName = staffNamesLong.isEmpty() ? " " : staffNamesLong[0].name(); if (staffName == "") { QList<StaffName>& staffNamesShort = currentStaff->part()->instrument()->shortNames(); staffName = staffNamesShort.isEmpty() ? "" : staffNamesShort[0].name(); } Text* newName = new Text(_score); newName->setXmlText(staffName); newName->setParent(parent); newName->setTrack(e->track()); newName->setColor(color); newName->textStyle().setFamily("FreeSans"); newName->textStyle().setSizeIsSpatiumDependent(true); newName->layout(); newName->setPlainText(newName->plainText()); newName->layout(); if (currentStaff->part()->staff(0) == currentStaff) { double _spatium = _score->spatium(); pos = QPointF (_score->styleP(StyleIdx::clefLeftMargin) + _widthClef, 0 - _spatium * 2); painter.translate(pos); newName->draw(&painter); painter.translate(-pos); } delete newName; // Draw the current Clef Clef* newClef = new Clef(_score); ClefType currentClef = currentStaff->clef(_currentMeasureTick); newClef->setClefType(currentClef); newClef->setParent(parent); newClef->setTrack(e->track()); newClef->setColor(color); newClef->layout(); pos = QPointF(_score->styleP(StyleIdx::clefLeftMargin), 0); painter.translate(pos); newClef->draw(&painter); pos = QPointF(_widthClef,0); painter.translate(pos); delete newClef; // Draw the current KeySignature KeySig* newKs = new KeySig(_score); KeySigEvent currentKeySigEvent = currentStaff->keySigEvent(_currentMeasureTick); newKs->setKeySigEvent(currentKeySigEvent); // The Parent and the track must be set to have the key signature layout adjusted to different clefs // This also adds naturals to the key signature (if set in the score style) newKs->setParent(parent); newKs->setTrack(e->track()); newKs->setColor(color); newKs->setHideNaturals(true); pos = QPointF(_score->styleP(StyleIdx::keysigLeftMargin),0); painter.translate(pos); newKs->layout(); newKs->draw(&painter); delete newKs; pos = QPointF(_widthKeySig + _xPosTimeSig, 0); painter.translate(pos); // Draw the current TimeSignature TimeSig* newTs = new TimeSig(_score); // Try to get local time signature, if not, get the current measure one TimeSig* currentTimeSig = currentStaff->timeSig(_currentMeasureTick); if (currentTimeSig) { newTs->setFrom(currentTimeSig); newTs->setParent(parent); newTs->setTrack(e->track()); newTs->setColor(color); newTs->layout(); pos = QPointF(_score->styleP(StyleIdx::timesigLeftMargin),0); painter.translate(pos); newTs->draw(&painter); delete newTs; } pos = QPointF(_offsetPanel + _widthClef + _widthKeySig + _xPosTimeSig + _leftMarginTotal, e->pagePos().y()); painter.translate(-pos); } } painter.restore(); }