LCOV - code coverage report
Current view: top level - src/engraving/dom - bracket.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 24.4 % 160 39
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 "bracket.h"
      24              : 
      25              : #include "types/typesconv.h"
      26              : 
      27              : #include "bracketitem.h"
      28              : #include "instrumentname.h"
      29              : #include "measure.h"
      30              : #include "score.h"
      31              : #include "staff.h"
      32              : #include "system.h"
      33              : #include "text.h"
      34              : 
      35              : #include "log.h"
      36              : 
      37              : using namespace mu;
      38              : using namespace mu::engraving;
      39              : using namespace muse::draw;
      40              : 
      41              : //---------------------------------------------------------
      42              : //   Bracket
      43              : //---------------------------------------------------------
      44              : 
      45         2069 : Bracket::Bracket(DummyParentOr<EngravingItem> parent)
      46         2069 :     : EngravingItem(ElementType::BRACKET, parent)
      47              : {
      48         2069 :     m_ay1          = 0;
      49         2069 :     m_firstStaff  = 0;
      50         2069 :     m_lastStaff   = 0;
      51         2069 :     m_labelType   = InstrumentNameType::LONG;
      52         2069 :     m_bi          = 0;
      53         2069 :     m_braceSymbol = SymId::noSym;
      54         2069 :     m_magx        = 1.;
      55         2069 :     setGenerated(true);       // brackets are not saved
      56         2069 : }
      57              : 
      58         3972 : Bracket::~Bracket()
      59              : {
      60         1986 :     if (m_text) {
      61            0 :         delete m_text;
      62              :     }
      63         3972 : }
      64              : 
      65          122 : void Bracket::scanElements(std::function<void(EngravingItem*)> func)
      66              : {
      67          122 :     if (m_text) {
      68            0 :         m_text->scanElements(func);
      69              :     }
      70              : 
      71          122 :     EngravingItem::scanElements(func);
      72          122 : }
      73              : 
      74              : //---------------------------------------------------------
      75              : //   setStaffSpan
      76              : //---------------------------------------------------------
      77              : 
      78         3550 : void Bracket::setStaffSpan(size_t a, size_t b)
      79              : {
      80         3550 :     m_firstStaff = a;
      81         3550 :     m_lastStaff = b;
      82              : 
      83         7100 :     if (bracketType() == BracketType::BRACE
      84         3550 :         && style().styleSt(Sid::musicalSymbolFont) != "Emmentaler" && style().styleSt(Sid::musicalSymbolFont) != "Gonville") {
      85         1721 :         int v = static_cast<int>(m_lastStaff - m_firstStaff + 1);
      86              : 
      87              :         // if staves inner staves are hidden, decrease span
      88         5151 :         for (size_t staffIndex = m_firstStaff; staffIndex <= m_lastStaff; ++staffIndex) {
      89         3430 :             if (system() && !system()->staff(staffIndex)->show()) {
      90            0 :                 --v;
      91              :             }
      92              :         }
      93              : 
      94         1721 :         if (style().styleSt(Sid::musicalSymbolFont) == "Leland") {
      95         1721 :             v = std::min(4, v);
      96              :         }
      97              : 
      98              :         // 1.625 is a "magic" number based on akkoladeDistance/4.0 (default value 6.5).
      99         1721 :         m_magx = v + ((v - 1) * 1.625);
     100              : 
     101         1721 :         if (v == 1) {
     102           12 :             m_braceSymbol = SymId::braceSmall;
     103         1709 :         } else if (v <= 2) {
     104         1709 :             m_braceSymbol = SymId::brace;
     105            0 :         } else if (v <= 3) {
     106            0 :             m_braceSymbol = SymId::braceLarge;
     107              :         } else {
     108            0 :             m_braceSymbol = SymId::braceLarger;
     109              :         }
     110              :     }
     111         3550 : }
     112              : 
     113            0 : bool Bracket::isEditable() const
     114              : {
     115            0 :     return true;
     116              : }
     117              : 
     118            0 : bool Bracket::needStartEditingAfterSelecting() const
     119              : {
     120            0 :     return true;
     121              : }
     122              : 
     123              : //---------------------------------------------------------
     124              : //   startEdit
     125              : //---------------------------------------------------------
     126              : 
     127            0 : void Bracket::startEdit(EditData& ed)
     128              : {
     129            0 :     EngravingItem::startEdit(ed);
     130            0 :     m_ay1 = pagePos().y();
     131            0 : }
     132              : 
     133              : //---------------------------------------------------------
     134              : //   gripsPositions
     135              : //---------------------------------------------------------
     136              : 
     137            0 : std::vector<PointF> Bracket::gripsPositions(const EditData&) const
     138              : {
     139            0 :     return { PointF(0.0, ldata()->bracketHeight()) + pagePos() };
     140              : }
     141              : 
     142              : //---------------------------------------------------------
     143              : //   endEdit
     144              : //---------------------------------------------------------
     145              : 
     146            0 : void Bracket::endEdit(EditData& ed)
     147              : {
     148            0 :     triggerLayoutAll();
     149            0 :     ed.clear(); // score layout invalidates element
     150            0 : }
     151              : 
     152            0 : void Bracket::dragGrip(EditData& ed)
     153              : {
     154            0 :     double bracketHeight = ldata()->bracketHeight();
     155            0 :     bracketHeight += ed.delta.y();
     156            0 :     mutldata()->bracketHeight.set_value(bracketHeight);
     157            0 : }
     158              : 
     159              : //---------------------------------------------------------
     160              : //   endDragGrip
     161              : //    snap to nearest staff
     162              : //---------------------------------------------------------
     163              : 
     164            0 : void Bracket::endDragGrip(EditData&)
     165              : {
     166            0 :     double ay2 = m_ay1 + ldata()->bracketHeight();
     167              : 
     168            0 :     staff_idx_t staffIdx1 = staffIdx();
     169              :     staff_idx_t staffIdx2;
     170            0 :     size_t n = system()->staves().size();
     171            0 :     if (staffIdx1 + 1 >= n) {
     172            0 :         staffIdx2 = staffIdx1;
     173              :     } else {
     174            0 :         double ay  = layoutParent()->pagePos().y();
     175            0 :         System* s = system();
     176            0 :         double y   = s->staff(staffIdx1)->y() + ay;
     177            0 :         double h1  = staff()->staffHeight();
     178              : 
     179            0 :         for (staffIdx2 = staffIdx1 + 1; staffIdx2 < n; ++staffIdx2) {
     180            0 :             double h = s->staff(staffIdx2)->y() + ay - y;
     181            0 :             if (ay2 < (y + (h + h1) * .5)) {
     182            0 :                 break;
     183              :             }
     184            0 :             y += h;
     185              :         }
     186            0 :         staffIdx2 -= 1;
     187              :     }
     188              : 
     189            0 :     double sy = system()->staff(staffIdx1)->y();
     190            0 :     double ey = system()->staff(staffIdx2)->y() + score()->staff(staffIdx2)->staffHeight();
     191            0 :     mutldata()->bracketHeight.set_value(ey - sy);
     192            0 :     bracketItem()->undoChangeProperty(Pid::BRACKET_SPAN, staffIdx2 - staffIdx1 + 1);
     193            0 : }
     194              : 
     195              : //---------------------------------------------------------
     196              : //   acceptDrop
     197              : //---------------------------------------------------------
     198              : 
     199            0 : bool Bracket::acceptDrop(EditData& data) const
     200              : {
     201            0 :     return data.dropElement->type() == ElementType::BRACKET;
     202              : }
     203              : 
     204              : //---------------------------------------------------------
     205              : //   drop
     206              : //---------------------------------------------------------
     207              : 
     208            0 : EngravingItem* Bracket::drop(Transaction&, EditData& data)
     209              : {
     210            0 :     EngravingItem* e = data.dropElement;
     211            0 :     Bracket* b = 0;
     212            0 :     if (e->isBracket()) {
     213            0 :         b = toBracket(e);
     214            0 :         undoChangeProperty(Pid::SYSTEM_BRACKET, int(b->bracketType()));
     215              :     }
     216            0 :     delete e;
     217            0 :     return this;
     218              : }
     219              : 
     220            0 : bool Bracket::isEditAllowed(EditData& ed) const
     221              : {
     222            0 :     if (ed.key == Key_Up && span() > 1) {
     223            0 :         return true;
     224              :     }
     225            0 :     if (ed.key == Key_Down && m_lastStaff < system()->staves().size() - 1) {
     226            0 :         return true;
     227              :     }
     228              : 
     229            0 :     if (!(ed.modifiers & ShiftModifier)) {
     230            0 :         return false;
     231              :     }
     232              : 
     233            0 :     if (ed.key == Key_Left) {
     234            0 :         return true;
     235              :     }
     236            0 :     if (ed.key == Key_Right) {
     237            0 :         if (bracketItem()->column() == 0) {
     238            0 :             return true;
     239              :         }
     240            0 :         return true;
     241              :     }
     242              : 
     243            0 :     return false;
     244              : }
     245              : 
     246              : //---------------------------------------------------------
     247              : //   edit
     248              : //    return true if event is accepted
     249              : //---------------------------------------------------------
     250              : 
     251            0 : bool Bracket::edit(EditData& ed)
     252              : {
     253            0 :     if (!isEditAllowed(ed)) {
     254            0 :         return false;
     255              :     }
     256              : 
     257            0 :     if (ed.key == Key_Up && span() > 1) {
     258            0 :         bracketItem()->undoChangeProperty(Pid::BRACKET_SPAN, static_cast<int>(span()) - 1);
     259            0 :         return true;
     260              :     }
     261            0 :     if (ed.key == Key_Down && m_lastStaff < system()->staves().size() - 1) {
     262            0 :         bracketItem()->undoChangeProperty(Pid::BRACKET_SPAN, static_cast<int>(span()) + 1);
     263            0 :         return true;
     264              :     }
     265              : 
     266            0 :     if (ed.key == Key_Left) {
     267            0 :         bracketItem()->undoChangeProperty(Pid::BRACKET_COLUMN, bracketItem()->column() + 1);
     268            0 :         return true;
     269              :     }
     270            0 :     if (ed.key == Key_Right) {
     271            0 :         if (bracketItem()->column() == 0) {
     272            0 :             return true;
     273              :         }
     274            0 :         bracketItem()->undoChangeProperty(Pid::BRACKET_COLUMN, bracketItem()->column() - 1);
     275            0 :         return true;
     276              :     }
     277            0 :     return false;
     278              : }
     279              : 
     280              : //---------------------------------------------------------
     281              : //   getProperty
     282              : //---------------------------------------------------------
     283              : 
     284            0 : PropertyValue Bracket::getProperty(Pid id) const
     285              : {
     286            0 :     PropertyValue v = EngravingItem::getProperty(id);
     287            0 :     if (!v.isValid()) {
     288            0 :         v = m_bi->getProperty(id);
     289              :     }
     290            0 :     return v;
     291            0 : }
     292              : 
     293              : //---------------------------------------------------------
     294              : //   setProperty
     295              : //---------------------------------------------------------
     296              : 
     297            0 : bool Bracket::setProperty(Pid id, const PropertyValue& v)
     298              : {
     299            0 :     return m_bi->setProperty(id, v);
     300              : }
     301              : 
     302              : //---------------------------------------------------------
     303              : //   propertyDefault
     304              : //---------------------------------------------------------
     305              : 
     306            0 : PropertyValue Bracket::propertyDefault(Pid id) const
     307              : {
     308            0 :     if (id == Pid::BRACKET_COLUMN) {
     309            0 :         return size_t(0);
     310              :     }
     311            0 :     PropertyValue v = EngravingItem::propertyDefault(id);
     312            0 :     if (!v.isValid()) {
     313            0 :         v = m_bi->propertyDefault(id);
     314              :     }
     315            0 :     return v;
     316            0 : }
     317              : 
     318              : //---------------------------------------------------------
     319              : //   subtypeUserName
     320              : //---------------------------------------------------------
     321              : 
     322            0 : muse::TranslatableString Bracket::subtypeUserName() const
     323              : {
     324            0 :     return TConv::userName(bracketType());
     325              : }
     326              : 
     327              : //---------------------------------------------------------
     328              : //   undoChangeProperty
     329              : //---------------------------------------------------------
     330              : 
     331            0 : void Bracket::undoChangeProperty(Pid id, const PropertyValue& v, PropertyFlags ps)
     332              : {
     333            0 :     if (id == Pid::COLOR) {
     334            0 :         setColor(v.value<Color>());
     335              :     }
     336              : 
     337              :     // brackets do not survive layout() and therefore cannot be on
     338              :     // the undo stack; delegate to BracketItem:
     339            0 :     BracketItem* bi = bracketItem();
     340            0 :     bi->undoChangeProperty(id, v, ps);
     341            0 : }
     342              : 
     343           76 : Fraction Bracket::tick() const
     344              : {
     345           76 :     if (measure()) {
     346           76 :         return measure()->tick();
     347              :     }
     348            0 :     return EngravingItem::tick();
     349              : }
     350              : 
     351              : //---------------------------------------------------------
     352              : //   setSelected
     353              : //---------------------------------------------------------
     354              : 
     355            0 : void Bracket::setSelected(bool f)
     356              : {
     357            0 :     m_bi->setSelected(f);
     358            0 :     if (m_text) {
     359            0 :         m_text->setSelected(f);
     360              :     }
     361              : 
     362            0 :     EngravingItem::setSelected(f);
     363            0 : }
     364              : 
     365          407 : bool Bracket::intersects(const Bracket* other) const
     366              : {
     367          407 :     return m_firstStaff <= other->m_lastStaff && m_lastStaff >= other->m_firstStaff;
     368              : }
     369              : 
     370            0 : bool Bracket::contains(staff_idx_t staffIdx) const
     371              : {
     372            0 :     return staffIdx >= m_firstStaff && staffIdx <= m_lastStaff;
     373              : }
        

Generated by: LCOV version 2.0-1