void ContinuousPanel::paint(const QRect&, QPainter& painter) { qreal _offsetPanel = 0; qreal _y = 0; qreal _oldWidth = 0; // The last final panel width qreal _newWidth = 0; // New panel width qreal _height = 0; qreal _leftMarginTotal = 0; // Sum of all elments left margin qreal _panelRightPadding = 5; // Extra space for the panel after last element Measure* measure = _score->firstMeasure(); if (!_active || !measure) { _visible = false; return; } if (measure->mmRest()) { measure = measure->mmRest(); } System* system = measure->system(); if (system == 0) { _visible = false; return; } Segment* s = measure->first(); double _spatium = _score->spatium(); if (_width <= 0) _width = s->x(); // // Set panel height for whole system // _height = 6 * _spatium; _y = system->staffYpage(0) + system->page()->pos().y(); double y2 = 0.0; for (int i = 0; i < _score->nstaves(); ++i) { SysStaff* ss = system->staff(i); if (!ss->show() || !_score->staff(i)->show()) continue; y2 = ss->y() + ss->bbox().height(); } _height += y2 + 6*_spatium; _y -= 6 * _spatium; // // Check elements at current panel position // _offsetPanel = -(_sv->xoffset()) / _sv->mag(); _rect = QRect(_offsetPanel + _width, _y, 1, _height); Page* page = _score->pages().front(); QList<Element*> el = page->items(_rect); if (el.empty()) { _visible = false; return; } qStableSort(el.begin(), el.end(), elementLessThan); const Measure*_currentMeasure = 0; for (const Element* e : el) { e->itemDiscovered = 0; if (!e->visible() && !_score->showInvisible()) continue; if (e->isMeasure()) { _currentMeasure = toMeasure(e); break; } } if (!_currentMeasure) return; // Don't show panel if staff names are visible if (_currentMeasure == _score->firstMeasure() && _sv->toPhysical(_currentMeasure->canvasPos()).x() > 0) { _visible = false; return; } qreal _xPosMeasure = _currentMeasure->canvasX(); qreal _measureWidth = _currentMeasure->width(); int tick = _currentMeasure->tick(); Fraction _currentTimeSig = _currentMeasure->timesig(); //qDebug() << "_sv->xoffset()=" <<_sv->xoffset() << " _sv->mag()="<< _sv->mag() <<" s->x=" << s->x() << " width=" << _width << " currentMeasure=" << _currentMeasure->x() << " _xPosMeasure=" << _xPosMeasure; //--------------------------------------------------------- // findElementWidths // determines the max width for each element types //--------------------------------------------------------- // The first pass serves to get the maximum width for each elements qreal lineWidthName = 0; qreal _widthClef = 0; qreal _widthKeySig = 0; qreal _widthTimeSig = 0; qreal _xPosTimeSig = 0; for (const Element* e : el) { e->itemDiscovered = 0; if (!e->visible() && !_score->showInvisible()) continue; if (e->isRest() && toRest(e)->isGap()) continue; if (e->isStaffLines()) { Staff* currentStaff = _score->staff(e->staffIdx()); Segment* parent = _score->tick2segment(tick); // Find maximum width for the 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->textStyle().setFamily("FreeSans"); newName->textStyle().setSizeIsSpatiumDependent(true); newName->layout(); newName->setPlainText(newName->plainText()); newName->layout(); // Find maximum width for the current Clef Clef* newClef = new Clef(_score); ClefType currentClef = currentStaff->clef(tick); newClef->setClefType(currentClef); newClef->setParent(parent); newClef->setTrack(e->track()); newClef->layout(); if (newClef->width() > _widthClef) _widthClef = newClef->width(); // Find maximum width for the current KeySignature KeySig* newKs = new KeySig(_score); KeySigEvent currentKeySigEvent = currentStaff->keySigEvent(tick); 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->setHideNaturals(true); newKs->layout(); if (newKs->width() > _widthKeySig) _widthKeySig = newKs->width(); // Find maximum width for 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(tick); if (currentTimeSig) newTs->setFrom(currentTimeSig); else newTs->setSig(Fraction(_currentTimeSig.numerator(), _currentTimeSig.denominator()), TimeSigType::NORMAL); newTs->setParent(parent); newTs->setTrack(e->track()); newTs->layout(); if ((newName->width() > lineWidthName) && (newName->xmlText() != "")) lineWidthName = newName->width(); if (newTs->width() > _widthTimeSig) _widthTimeSig = newTs->width(); delete newClef; delete newName; delete newKs; delete newTs; } } _leftMarginTotal = _score->styleP(StyleIdx::clefLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::keysigLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::timesigLeftMargin); _newWidth = _widthClef + _widthKeySig + _widthTimeSig + _leftMarginTotal + _panelRightPadding; _xPosMeasure -= _offsetPanel; lineWidthName += _score->spatium() + _score->styleP(StyleIdx::clefLeftMargin) + _widthClef; if (_newWidth < lineWidthName) { _newWidth = lineWidthName; _oldWidth = 0; } if (_oldWidth == 0) { _oldWidth = _newWidth; _width = _newWidth; } else if (_newWidth > 0) { if (_newWidth == _width) { _oldWidth = _width; _width = _newWidth; } else if (((_xPosMeasure <= _newWidth) && (_xPosMeasure >= _oldWidth)) || ((_xPosMeasure >= _newWidth) && (_xPosMeasure <= _oldWidth))) _width = _xPosMeasure; else if (((_xPosMeasure+_measureWidth <= _newWidth) && (_xPosMeasure+_measureWidth >= _oldWidth)) || ((_xPosMeasure+_measureWidth >= _newWidth) && (_xPosMeasure+_measureWidth <= _oldWidth))) _width = _xPosMeasure+_measureWidth; else { _oldWidth = _width; _width = _newWidth; } } _rect = QRect(0, _y, _width, _height); //==================== painter.save(); // 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 = QString("#%1").arg(_currentMeasure->no()+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) { if (!e->visible() && !_score->showInvisible()) continue; if (e->isRest() && toRest(e)->isGap()) continue; if (e->isStaffLines()) { painter.save(); Staff* currentStaff = _score->staff(e->staffIdx()); Segment* parent = _score->tick2segmentMM(tick); pos = QPointF (_offsetPanel, e->pagePos().y()); painter.translate(pos); // Draw staff lines StaffLines newStaffLines(*toStaffLines(e)); newStaffLines.setParent(parent); newStaffLines.setTrack(e->track()); newStaffLines.layout(); newStaffLines.setColor(color); newStaffLines.setWidth(bg.width()); newStaffLines.draw(&painter); // Draw barline BarLine barLine(_score); barLine.setBarLineType(BarLineType::NORMAL); barLine.setParent(parent); barLine.setTrack(e->track()); barLine.setSpan(currentStaff->barLineSpan()); barLine.setSpanFrom(currentStaff->barLineFrom()); barLine.setSpanTo(currentStaff->barLineTo()); barLine.layout(); barLine.setColor(color); barLine.draw(&painter); // 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, -_spatium * 2); painter.translate(pos); newName->draw(&painter); painter.translate(-pos); } delete newName; qreal posX = 0.0; // Draw the current Clef Clef clef(_score); clef.setClefType(currentStaff->clef(tick)); clef.setParent(parent); clef.setTrack(e->track()); clef.setColor(color); clef.layout(); posX += _score->styleP(StyleIdx::clefLeftMargin); clef.drawAt(&painter, QPointF(posX, clef.pos().y())); posX += _widthClef; // Draw the current KeySignature KeySig newKs(_score); newKs.setKeySigEvent(currentStaff->keySigEvent(tick)); // 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); newKs.layout(); posX += _score->styleP(StyleIdx::keysigLeftMargin); newKs.drawAt(&painter, QPointF(posX, 0.0)); posX += _widthKeySig + _xPosTimeSig; // Draw the current TimeSignature TimeSig newTs(_score); // Try to get local time signature, if not, get the current measure one TimeSig* currentTimeSig = currentStaff->timeSig(tick); if (currentTimeSig) { newTs.setFrom(currentTimeSig); newTs.setParent(parent); newTs.setTrack(e->track()); newTs.setColor(color); newTs.layout(); posX += _score->styleP(StyleIdx::timesigLeftMargin); newTs.drawAt(&painter, QPointF(posX, 0.0)); } painter.restore(); } } painter.restore(); _visible = true; }
void ContinuousPanel::findElementWidths(const QList<Element*>& el) { // The first pass serves to get the maximum width for each elements qreal lineWidthName = 0; _widthClef = 0; _widthKeySig = 0; _widthTimeSig = 0; _xPosTimeSig = 0; 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->tick2segment(_currentMeasureTick); // Find maximum width for the 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->textStyle().setFamily("FreeSans"); newName->textStyle().setSizeIsSpatiumDependent(true); newName->layout(); newName->setPlainText(newName->plainText()); newName->layout(); // Find maximum width for the current Clef Clef* newClef = new Clef(_score); ClefType currentClef = currentStaff->clef(_currentMeasureTick); newClef->setClefType(currentClef); newClef->setParent(parent); newClef->setTrack(e->track()); newClef->layout(); // Find maximum width for 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->setHideNaturals(true); newKs->layout(); // Find maximum width for 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); else newTs->setSig(_currentTimeSig.numerator(), _currentTimeSig.denominator(), TimeSigType::NORMAL); newTs->setParent(parent); newTs->setTrack(e->track()); newTs->layout(); if ((newName->width() > lineWidthName) && (newName->xmlText() != "")) lineWidthName = newName->width(); if (newClef->width() > _widthClef) _widthClef = newClef->width(); if (newKs->width() > _widthKeySig) _widthKeySig = newKs->width(); if (newTs->width() > _widthTimeSig) _widthTimeSig = newTs->width(); delete newClef; delete newName; delete newKs; delete newTs; } } _leftMarginTotal = _score->styleP(StyleIdx::clefLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::keysigLeftMargin); _leftMarginTotal += _score->styleP(StyleIdx::timesigLeftMargin); _newWidth = _widthClef + _widthKeySig + _widthTimeSig + _leftMarginTotal + _panelRightPadding; _xPosMeasure -= _offsetPanel; lineWidthName += _score->spatium() + _score->styleP(StyleIdx::clefLeftMargin) + _widthClef; if (_newWidth < lineWidthName) { _newWidth = lineWidthName; _oldWidth = 0; } if (_oldWidth == 0) { _oldWidth = _newWidth; _width = _newWidth; } else if (_newWidth > 0) { if (_newWidth == _width) { _oldWidth = _width; _width = _newWidth; } else if (((_xPosMeasure <= _newWidth) && (_xPosMeasure >= _oldWidth)) || ((_xPosMeasure >= _newWidth) && (_xPosMeasure <= _oldWidth))) _width = _xPosMeasure; else if (((_xPosMeasure+_measureWidth <= _newWidth) && (_xPosMeasure+_measureWidth >= _oldWidth)) || ((_xPosMeasure+_measureWidth >= _newWidth) && (_xPosMeasure+_measureWidth <= _oldWidth))) _width = _xPosMeasure+_measureWidth; else { _oldWidth = _width; _width = _newWidth; } } _rect = QRect(0, _y, _width, _height); }