LCOV - code coverage report
Current view: top level - src/engraving/dom - slurtie.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 57.8 % 237 137
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "slurtie.h"
      24              : 
      25              : #include "iengravingconfiguration.h" // IWYU pragma: keep
      26              : 
      27              : #include "../editing/elementeditdata.h"
      28              : #include "../editing/mscoreview.h"
      29              : #include "../rendering/iscorerenderer.h"
      30              : 
      31              : #include "note.h"
      32              : #include "page.h"
      33              : #include "score.h"
      34              : #include "system.h"
      35              : 
      36              : #include "log.h"
      37              : 
      38              : using namespace mu;
      39              : using namespace muse::draw;
      40              : using namespace mu::engraving;
      41              : 
      42              : namespace mu::engraving {
      43              : //---------------------------------------------------------
      44              : //   SlurTieSegment
      45              : //---------------------------------------------------------
      46              : 
      47         2520 : SlurTieSegment::SlurTieSegment(const ElementType& type, SlurTie* sp)
      48         2520 :     : SpannerSegment(type, sp)
      49              : {
      50         2520 :     setFlag(ElementFlag::ON_STAFF, true);
      51         2520 : }
      52              : 
      53          481 : SlurTieSegment::SlurTieSegment(const SlurTieSegment& b)
      54          481 :     : SpannerSegment(b)
      55              : {
      56         3367 :     for (int i = 0; i < int(Grip::GRIPS); ++i) {
      57         2886 :         m_ups[i]   = b.m_ups[i];
      58         2886 :         m_ups[i].p = PointF();
      59              :     }
      60          481 : }
      61              : 
      62            0 : bool SlurTieSegment::isEditAllowed(EditData& ed) const
      63              : {
      64            0 :     if (ed.key == Key_Home && !(ed.modifiers & ~KeyboardModifier::KeypadModifier) && ed.hasCurrentGrip()) {
      65            0 :         return true;
      66              :     }
      67              : 
      68            0 :     return false;
      69              : }
      70              : 
      71              : //---------------------------------------------------------
      72              : //   edit
      73              : //    return true if event is accepted
      74              : //---------------------------------------------------------
      75              : 
      76            0 : bool SlurTieSegment::edit(EditData& ed)
      77              : {
      78            0 :     if (!isEditAllowed(ed)) {
      79            0 :         return false;
      80              :     }
      81              : 
      82            0 :     if (ed.key == Key_Home && !(ed.modifiers & ~KeyboardModifier::KeypadModifier)) {
      83            0 :         if (ed.hasCurrentGrip()) {
      84            0 :             startDragGrip(ed);
      85            0 :             if (ed.curGrip == Grip::SHOULDER) {
      86            0 :                 ups(Grip::BEZIER1).off = PointF();
      87            0 :                 ups(Grip::BEZIER2).off = PointF();
      88              :             } else {
      89            0 :                 ups(ed.curGrip).off = PointF();
      90              :             }
      91            0 :             renderer()->layoutItem(spanner());
      92            0 :             endDragGrip(ed);
      93              :         }
      94            0 :         return true;
      95              :     }
      96            0 :     return false;
      97              : }
      98              : 
      99              : //---------------------------------------------------------
     100              : //   gripAnchorLines
     101              : //---------------------------------------------------------
     102              : 
     103            0 : std::vector<LineF> SlurTieSegment::gripAnchorLines(Grip grip) const
     104              : {
     105            0 :     std::vector<LineF> result;
     106              : 
     107            0 :     if (!system() || (grip != Grip::START && grip != Grip::END)) {
     108            0 :         return result;
     109              :     }
     110              : 
     111            0 :     PointF sp(system()->pagePos());
     112            0 :     PointF pp(pagePos());
     113            0 :     PointF p1(ups(Grip::START).p + pp);
     114            0 :     PointF p2(ups(Grip::END).p + pp);
     115              : 
     116            0 :     PointF anchorPosition;
     117            0 :     int gripIndex = static_cast<int>(grip);
     118              : 
     119            0 :     switch (spannerSegmentType()) {
     120            0 :     case SpannerSegmentType::SINGLE:
     121            0 :         anchorPosition = (grip == Grip::START ? p1 : p2);
     122            0 :         break;
     123              : 
     124            0 :     case SpannerSegmentType::BEGIN:
     125            0 :         anchorPosition = (grip == Grip::START ? p1 : system()->pageBoundingRect().topRight());
     126            0 :         break;
     127              : 
     128            0 :     case SpannerSegmentType::MIDDLE:
     129            0 :         anchorPosition = (grip == Grip::START ? sp : system()->pageBoundingRect().topRight());
     130            0 :         break;
     131              : 
     132            0 :     case SpannerSegmentType::END:
     133            0 :         anchorPosition = (grip == Grip::START ? sp : p2);
     134            0 :         break;
     135              :     }
     136              : 
     137            0 :     const Page* p = system()->page();
     138            0 :     const PointF pageOffset = p ? p->pos() : PointF();
     139            0 :     result.push_back(LineF(anchorPosition, gripsPositions().at(gripIndex)).translated(pageOffset));
     140              : 
     141            0 :     return result;
     142            0 : }
     143              : 
     144              : //---------------------------------------------------------
     145              : //   move
     146              : //---------------------------------------------------------
     147              : 
     148            0 : void SlurTieSegment::move(const PointF& s)
     149              : {
     150            0 :     EngravingItem::move(s);
     151            0 :     for (int k = 0; k < int(Grip::GRIPS); ++k) {
     152            0 :         m_ups[k].p += s;
     153              :     }
     154            0 : }
     155              : 
     156              : //---------------------------------------------------------
     157              : //   spatiumChanged
     158              : //---------------------------------------------------------
     159              : 
     160           16 : void SlurTieSegment::spatiumChanged(double oldValue, double newValue)
     161              : {
     162           16 :     EngravingItem::spatiumChanged(oldValue, newValue);
     163           16 :     double diff = newValue / oldValue;
     164          112 :     for (UP& u : m_ups) {
     165           96 :         u.off *= diff;
     166              :     }
     167           16 : }
     168              : 
     169              : //---------------------------------------------------------
     170              : //   gripsPositions
     171              : //---------------------------------------------------------
     172              : 
     173            0 : std::vector<PointF> SlurTieSegment::gripsPositions(const EditData&) const
     174              : {
     175            0 :     const int ngrips = gripsCount();
     176            0 :     std::vector<PointF> grips(ngrips);
     177              : 
     178            0 :     const PointF p(pagePos());
     179            0 :     for (int i = 0; i < ngrips; ++i) {
     180            0 :         grips[i] = m_ups[i].p + m_ups[i].off + p;
     181              :     }
     182              : 
     183            0 :     return grips;
     184            0 : }
     185              : 
     186          940 : bool SlurTieSegment::isUserModified() const
     187              : {
     188         1877 :     return SpannerSegment::isUserModified() || !(visible() && autoplace()
     189          937 :                                                  && color() == configuration()->defaultColor()
     190          937 :                                                  && offset().isNull()
     191          937 :                                                  && ups(Grip::START).off.isNull()
     192          937 :                                                  && ups(Grip::BEZIER1).off.isNull()
     193          937 :                                                  && ups(Grip::BEZIER2).off.isNull()
     194         1877 :                                                  && ups(Grip::END).off.isNull());
     195              : }
     196              : 
     197              : //---------------------------------------------------------
     198              : //   startDragGrip
     199              : //---------------------------------------------------------
     200              : 
     201            0 : void SlurTieSegment::startDragGrip(EditData& ed)
     202              : {
     203            0 :     ElementEditDataPtr eed = ed.getData(this);
     204            0 :     IF_ASSERT_FAILED(eed) {
     205            0 :         return;
     206              :     }
     207            0 :     for (Pid i : { Pid::BEZIER_OFFSET1, Pid::BEZIER_OFFSET2, Pid::BEZIER_OFFSET3, Pid::BEZIER_OFFSET4, Pid::OFFSET }) {
     208            0 :         eed->pushProperty(i);
     209              :     }
     210            0 : }
     211              : 
     212              : //---------------------------------------------------------
     213              : //   endDragGrip
     214              : //---------------------------------------------------------
     215              : 
     216            0 : void SlurTieSegment::endDragGrip(EditData& ed)
     217              : {
     218            0 :     EngravingItem::endDragGrip(ed);
     219            0 :     triggerLayout();
     220            0 : }
     221              : 
     222              : //---------------------------------------------------------
     223              : //   propertyDelegate
     224              : //---------------------------------------------------------
     225              : 
     226        11995 : EngravingObject* SlurTieSegment::propertyDelegate(Pid pid) const
     227              : {
     228        11995 :     switch (pid) {
     229         3331 :     case Pid::SLUR_STYLE_TYPE:
     230              :     case Pid::SLUR_DIRECTION:
     231              :     case Pid::MASK_SLURTIE:
     232         3331 :         return slurTie();
     233         8664 :     default:
     234         8664 :         return SpannerSegment::propertyDelegate(pid);
     235              :     }
     236              : }
     237              : 
     238              : //---------------------------------------------------------
     239              : //   getProperty
     240              : //---------------------------------------------------------
     241              : 
     242         5048 : PropertyValue SlurTieSegment::getProperty(Pid propertyId) const
     243              : {
     244         5048 :     if (EngravingObject* e = const_cast<SlurTieSegment*>(this)->propertyDelegate(propertyId)) {
     245         3716 :         return e->getProperty(propertyId);
     246              :     }
     247              : 
     248         1332 :     switch (propertyId) {
     249           59 :     case Pid::BEZIER_OFFSET1:
     250           59 :         return ups(Grip::START).off;
     251           59 :     case Pid::BEZIER_OFFSET2:
     252           59 :         return ups(Grip::BEZIER1).off;
     253           59 :     case Pid::BEZIER_OFFSET3:
     254           59 :         return ups(Grip::BEZIER2).off;
     255           59 :     case Pid::BEZIER_OFFSET4:
     256           59 :         return ups(Grip::END).off;
     257         1096 :     default:
     258         1096 :         return SpannerSegment::getProperty(propertyId);
     259              :     }
     260              : }
     261              : 
     262              : //---------------------------------------------------------
     263              : //   setProperty
     264              : //---------------------------------------------------------
     265              : 
     266          117 : bool SlurTieSegment::setProperty(Pid propertyId, const PropertyValue& v)
     267              : {
     268          117 :     if (EngravingObject* e = const_cast<SlurTieSegment*>(this)->propertyDelegate(propertyId)) {
     269            5 :         return e->setProperty(propertyId, v);
     270              :     }
     271              : 
     272          112 :     switch (propertyId) {
     273            3 :     case Pid::BEZIER_OFFSET1:
     274            3 :         ups(Grip::START).off = v.value<PointF>();
     275            3 :         break;
     276            6 :     case Pid::BEZIER_OFFSET2:
     277            6 :         ups(Grip::BEZIER1).off = v.value<PointF>();
     278            6 :         break;
     279            5 :     case Pid::BEZIER_OFFSET3:
     280            5 :         ups(Grip::BEZIER2).off = v.value<PointF>();
     281            5 :         break;
     282            4 :     case Pid::BEZIER_OFFSET4:
     283            4 :         ups(Grip::END).off = v.value<PointF>();
     284            4 :         break;
     285           94 :     default:
     286           94 :         return SpannerSegment::setProperty(propertyId, v);
     287              :     }
     288           18 :     triggerLayout();
     289           18 :     return true;
     290              : }
     291              : 
     292              : //---------------------------------------------------------
     293              : //   propertyDefault
     294              : //---------------------------------------------------------
     295              : 
     296         1653 : PropertyValue SlurTieSegment::propertyDefault(Pid id) const
     297              : {
     298         1653 :     if (EngravingObject* e = const_cast<SlurTieSegment*>(this)->propertyDelegate(id)) {
     299          371 :         return e->propertyDefault(id);
     300              :     }
     301              : 
     302         1282 :     switch (id) {
     303          212 :     case Pid::BEZIER_OFFSET1:
     304              :     case Pid::BEZIER_OFFSET2:
     305              :     case Pid::BEZIER_OFFSET3:
     306              :     case Pid::BEZIER_OFFSET4:
     307          424 :         return PointF();
     308         1070 :     default:
     309         1070 :         return SpannerSegment::propertyDefault(id);
     310              :     }
     311              : }
     312              : 
     313              : //---------------------------------------------------------
     314              : //   reset
     315              : //---------------------------------------------------------
     316              : 
     317            0 : void SlurTieSegment::reset()
     318              : {
     319            0 :     EngravingItem::reset();
     320            0 :     undoResetProperty(Pid::BEZIER_OFFSET1);
     321            0 :     undoResetProperty(Pid::BEZIER_OFFSET2);
     322            0 :     undoResetProperty(Pid::BEZIER_OFFSET3);
     323            0 :     undoResetProperty(Pid::BEZIER_OFFSET4);
     324            0 :     slurTie()->reset();
     325            0 : }
     326              : 
     327              : //---------------------------------------------------------
     328              : //   undoChangeProperty
     329              : //---------------------------------------------------------
     330              : 
     331           30 : void SlurTieSegment::undoChangeProperty(Pid pid, const PropertyValue& val, PropertyFlags ps)
     332              : {
     333           30 :     if (pid == Pid::AUTOPLACE && (val.toBool() == true && !autoplace())) {
     334              :         // Switching autoplacement on. Save user-defined
     335              :         // placement properties to undo stack.
     336            3 :         undoPushProperty(Pid::BEZIER_OFFSET1);
     337            3 :         undoPushProperty(Pid::BEZIER_OFFSET2);
     338            3 :         undoPushProperty(Pid::BEZIER_OFFSET3);
     339            3 :         undoPushProperty(Pid::BEZIER_OFFSET4);
     340              :         // other will be saved in base classes.
     341              :     }
     342           30 :     SpannerSegment::undoChangeProperty(pid, val, ps);
     343           30 : }
     344              : 
     345              : //---------------------------------------------------------
     346              : //   SlurTie
     347              : //---------------------------------------------------------
     348              : 
     349         2358 : SlurTie::SlurTie(const ElementType& type, EngravingObject* parent)
     350         2358 :     : Spanner(type, parent)
     351              : {
     352         2358 :     m_slurDirection = DirectionV::AUTO;
     353         2358 :     m_up            = true;
     354         2358 :     m_styleType     = SlurStyleType::Solid;
     355         2358 :     m_maskSlurTie   = AutoOnOff::AUTO;
     356         2358 : }
     357              : 
     358          506 : SlurTie::SlurTie(const SlurTie& t)
     359          506 :     : Spanner(t)
     360              : {
     361          506 :     m_up            = t.m_up;
     362          506 :     m_slurDirection = t.m_slurDirection;
     363          506 :     m_styleType     = t.m_styleType;
     364          506 :     m_maskSlurTie   = t.m_maskSlurTie;
     365          506 : }
     366              : 
     367              : //---------------------------------------------------------
     368              : //   SlurTie
     369              : //---------------------------------------------------------
     370              : 
     371         2390 : SlurTie::~SlurTie()
     372              : {
     373         2390 : }
     374              : 
     375              : //---------------------------------------------------------
     376              : //   undoSetSlurDirection
     377              : //---------------------------------------------------------
     378              : 
     379            0 : void SlurTie::undoSetSlurDirection(DirectionV d)
     380              : {
     381            0 :     undoChangeProperty(Pid::SLUR_DIRECTION, PropertyValue::fromValue<DirectionV>(d));
     382            0 : }
     383              : 
     384              : //---------------------------------------------------------
     385              : //   getProperty
     386              : //---------------------------------------------------------
     387              : 
     388        16470 : PropertyValue SlurTie::getProperty(Pid propertyId) const
     389              : {
     390        16470 :     switch (propertyId) {
     391          967 :     case Pid::SLUR_STYLE_TYPE:
     392          967 :         return styleType();
     393          973 :     case Pid::SLUR_DIRECTION:
     394          973 :         return PropertyValue::fromValue<DirectionV>(slurDirection());
     395         4298 :     case Pid::MASK_SLURTIE:
     396         4298 :         return maskSlurTie();
     397        10232 :     default:
     398        10232 :         return Spanner::getProperty(propertyId);
     399              :     }
     400              : }
     401              : 
     402              : //---------------------------------------------------------
     403              : //   setProperty
     404              : //---------------------------------------------------------
     405              : 
     406          196 : bool SlurTie::setProperty(Pid propertyId, const PropertyValue& v)
     407              : {
     408          196 :     switch (propertyId) {
     409           18 :     case Pid::SLUR_STYLE_TYPE:
     410           18 :         setStyleType(v.value<SlurStyleType>());
     411           18 :         break;
     412           49 :     case Pid::SLUR_DIRECTION:
     413           49 :         setSlurDirection(v.value<DirectionV>());
     414           49 :         break;
     415            0 :     case Pid::MASK_SLURTIE:
     416            0 :         setMaskSlurTie(v.value<AutoOnOff>());
     417            0 :         break;
     418          129 :     default:
     419          129 :         return Spanner::setProperty(propertyId, v);
     420              :     }
     421           67 :     triggerLayout();
     422           67 :     return true;
     423              : }
     424              : 
     425              : //---------------------------------------------------------
     426              : //   propertyDefault
     427              : //---------------------------------------------------------
     428              : 
     429        12946 : PropertyValue SlurTie::propertyDefault(Pid id) const
     430              : {
     431        12946 :     switch (id) {
     432          967 :     case Pid::SLUR_STYLE_TYPE:
     433          967 :         return SlurStyleType::Solid;
     434          967 :     case Pid::SLUR_DIRECTION:
     435         1934 :         return PropertyValue::fromValue<DirectionV>(DirectionV::AUTO);
     436          967 :     case Pid::MASK_SLURTIE:
     437         1934 :         return AutoOnOff::AUTO;
     438        10045 :     default:
     439        10045 :         return Spanner::propertyDefault(id);
     440              :     }
     441              : }
     442              : 
     443              : //---------------------------------------------------------
     444              : //   fixupSegments
     445              : //---------------------------------------------------------
     446              : 
     447         5351 : void SlurTie::fixupSegments(unsigned nsegs)
     448              : {
     449         7329 :     Spanner::fixupSegments(nsegs, [this]() { return newSlurTieSegment(); });
     450         5351 : }
     451              : 
     452              : //---------------------------------------------------------
     453              : //   reset
     454              : //---------------------------------------------------------
     455              : 
     456            1 : void SlurTie::reset()
     457              : {
     458            1 :     EngravingItem::reset();
     459            1 :     undoResetProperty(Pid::SLUR_DIRECTION);
     460            1 :     undoResetProperty(Pid::SLUR_STYLE_TYPE);
     461            1 :     undoResetProperty(Pid::MASK_SLURTIE);
     462            1 : }
     463              : 
     464            0 : muse::TranslatableString SlurTie::subtypeUserName() const
     465              : {
     466            0 :     switch (m_styleType) {
     467            0 :     case SlurStyleType::Solid:
     468            0 :         return TranslatableString("engraving/slurstyletype", "Solid");
     469            0 :     case SlurStyleType::Dotted:
     470            0 :         return TranslatableString("engraving/slurstyletype", "Dotted");
     471            0 :     case SlurStyleType::Dashed:
     472            0 :         return TranslatableString("engraving/slurstyletype", "Dashed");
     473            0 :     case SlurStyleType::WideDashed:
     474            0 :         return TranslatableString("engraving/slurstyletype", "Wide dashed");
     475            0 :     default:
     476            0 :         return TranslatableString("engraving/slurstyletype", "Undefined");
     477              :     }
     478              : }
     479              : 
     480            0 : int SlurTieSegment::subtype() const
     481              : {
     482            0 :     return slurTie()->subtype();
     483              : }
     484              : 
     485            0 : muse::TranslatableString SlurTieSegment::subtypeUserName() const
     486              : {
     487            0 :     return slurTie()->subtypeUserName();
     488              : }
     489              : }
        

Generated by: LCOV version 2.0-1