    //=============================================================================
    //  MuseScore
    //  Music Composition & Notation
    //
    //  Copyright (C) 2002-2011 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 "box.h"
    #include "textframe.h"
    #include "text.h"
    #include "score.h"
    #include "barline.h"
    #include "repeat.h"
    #include "symbol.h"
    #include "system.h"
    #include "image.h"
    #include "layoutbreak.h"
    #include "fret.h"
    #include "mscore.h"
    #include "stafftext.h"
    #include "icon.h"
    #include "xml.h"
    #include "measure.h"
    #include "undo.h"

    namespace Ms {

    //---------------------------------------------------------
    //   Box
    //---------------------------------------------------------

    Box::Box(Score* score)
       : MeasureBase(score)
          {
          }

    //---------------------------------------------------------
    //   layout
    //---------------------------------------------------------

    void Box::layout()
          {
          MeasureBase::layout();
          for (Element* e : el()) {
                if (!e->isLayoutBreak())
                      e->layout();
                }
          }

    //---------------------------------------------------------
    //   computeMinWidth
    //---------------------------------------------------------

    void HBox::computeMinWidth()
          {
          setWidth(point(boxWidth()) + topGap() + bottomGap());  // top/bottom is really left/right
          }

    //---------------------------------------------------------
    //   draw
    //---------------------------------------------------------

    void Box::draw(QPainter* painter) const
          {
          if (score() && score()->printing())
                return;
          if (selected() || editMode || dropTarget() || score()->showFrames()) {
                qreal w = spatium() * .15;
                QPainterPathStroker stroker;
                stroker.setWidth(w);
                stroker.setJoinStyle(Qt::MiterJoin);
                stroker.setCapStyle(Qt::SquareCap);

                QVector<qreal> dashes ;
                dashes.append(1);
                dashes.append(3);
                stroker.setDashPattern(dashes);
                QPainterPath path;
                w *= .5;
                path.addRect(bbox().adjusted(w, w, -w, -w));
                QPainterPath stroke = stroker.createStroke(path);
                painter->setBrush(Qt::NoBrush);
                painter->fillPath(stroke, (selected() || editMode || dropTarget()) ? MScore::selectColor[0] : MScore::frameMarginColor);
                }
          }

    //---------------------------------------------------------
    //   startEdit
    //---------------------------------------------------------

    void Box::startEdit(EditData& ed)
          {
          Element::startEdit(ed);
          ed.grips   = 1;
          ed.curGrip = Grip::START;
          editMode   = true;
          }

    //---------------------------------------------------------
    //   edit
    //---------------------------------------------------------

    bool Box::edit(EditData&)
          {
          return false;
          }

    //---------------------------------------------------------
    //   startEditDrag
    //---------------------------------------------------------

    void Box::startEditDrag(EditData& ed)
          {
          ElementEditData* eed = ed.getData(this);
          if (isHBox())
                eed->pushProperty(P_ID::BOX_WIDTH);
          else
                eed->pushProperty(P_ID::BOX_HEIGHT);
          }

    //---------------------------------------------------------
    //   editDrag
    //---------------------------------------------------------

    void Box::editDrag(EditData& ed)
          {
          if (isVBox()) {
                _boxHeight = Spatium((ed.pos.y() - abbox().y()) / spatium());
                if (ed.vRaster) {
                      qreal vRaster = 1.0 / MScore::vRaster();
                      int n = lrint(_boxHeight.val() / vRaster);
                      _boxHeight = Spatium(vRaster * n);
                      }
                bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
                system()->setHeight(height());
                score()->setLayout(tick());
                }
          else {
                _boxWidth += Spatium(ed.delta.x() / spatium());
                if (ed.hRaster) {
                      qreal hRaster = 1.0 / MScore::hRaster();
                      int n = lrint(_boxWidth.val() / hRaster);
                      _boxWidth = Spatium(hRaster * n);
                      }
                score()->setLayout(tick());
                }
          layout();
          }

    //---------------------------------------------------------
    //   endEdit
    //---------------------------------------------------------

    void Box::endEdit(EditData&)
          {
          editMode = false;
          layout();
          }

    //---------------------------------------------------------
    //   updateGrips
    //---------------------------------------------------------

    void Box::updateGrips(EditData& ed) const
          {
          QRectF r(abbox());
          if (isHBox())
                ed.grip[0].translate(QPointF(r.right(), r.top() + r.height() * .5));
          else if (type() == ElementType::VBOX)
                ed.grip[0].translate(QPointF(r.x() + r.width() * .5, r.bottom()));
          }

    //---------------------------------------------------------
    //   write
    //---------------------------------------------------------

    void Box::write(XmlWriter& xml) const
          {
          xml.stag(name());
          writeProperties(xml);
          xml.etag();
          }

    //---------------------------------------------------------
    //   writeProperties
    //---------------------------------------------------------

    void Box::writeProperties(XmlWriter& xml) const
          {
          writeProperty(xml, P_ID::BOX_HEIGHT);
          writeProperty(xml, P_ID::BOX_WIDTH);
          writeProperty(xml, P_ID::TOP_GAP);
          writeProperty(xml, P_ID::BOTTOM_GAP);
          writeProperty(xml, P_ID::LEFT_MARGIN);
          writeProperty(xml, P_ID::RIGHT_MARGIN);
          writeProperty(xml, P_ID::TOP_MARGIN);
          writeProperty(xml, P_ID::BOTTOM_MARGIN);

          Element::writeProperties(xml);
          for (const Element* e : el())
                e->write(xml);
          }

    //---------------------------------------------------------
    //   read
    //---------------------------------------------------------

    void Box::read(XmlReader& e)
          {
          _leftMargin      = 0.0;
          _rightMargin     = 0.0;
          _topMargin       = 0.0;
          _bottomMargin    = 0.0;
          _boxHeight       = Spatium(0);     // override default set in constructor
          _boxWidth        = Spatium(0);
          bool keepMargins = false;        // whether original margins have to be kept when reading old file

          while (e.readNextStartElement()) {
                const QStringRef& tag(e.name());
                if (tag == "HBox") {
                      HBox* hb = new HBox(score());
                      hb->read(e);
                      add(hb);
                      keepMargins = true;     // in old file, box nesting used outer box margins
                      }
                else if (tag == "VBox") {
                      VBox* vb = new VBox(score());
                      vb->read(e);
                      add(vb);
                      keepMargins = true;     // in old file, box nesting used outer box margins
                      }
                else if (!Box::readProperties(e))
                      e.unknown();
                }

          // with .msc versions prior to 1.17, box margins were only used when nesting another box inside this box:
          // for backward compatibility set them to 0 in all other cases

          if (score()->mscVersion() <= 114 && (isHBox() || isVBox()) && !keepMargins)  {
                _leftMargin   = 0.0;
                _rightMargin  = 0.0;
                _topMargin    = 0.0;
                _bottomMargin = 0.0;
                }
          }

    //---------------------------------------------------------
    //   readProperties
    //---------------------------------------------------------

    bool Box::readProperties(XmlReader& e)
          {
          const QStringRef& tag(e.name());
          if (tag == "height")
                _boxHeight = Spatium(e.readDouble());
          else if (tag == "width")
                _boxWidth = Spatium(e.readDouble());
          else if (tag == "topGap") {
                _topGap = e.readDouble();
                if (score()->mscVersion() >= 206)
                      _topGap *= score()->spatium();
                topGapStyle = PropertyFlags::UNSTYLED;
                }
          else if (tag == "bottomGap") {
                _bottomGap = e.readDouble();
                 if (score()->mscVersion() >= 206)
                      _bottomGap *= score()->spatium();
                bottomGapStyle = PropertyFlags::UNSTYLED;
                }
          else if (tag == "leftMargin")
                _leftMargin = e.readDouble();
          else if (tag == "rightMargin")
                _rightMargin = e.readDouble();
          else if (tag == "topMargin")
                _topMargin = e.readDouble();
          else if (tag == "bottomMargin")
                _bottomMargin = e.readDouble();
          else if (tag == "Text") {
                Text* t;
                if (isTBox()) {
                      t = toTBox(this)->text();
                      t->read(e);
                      }
                else {
                      t = new Text(score());
                      t->read(e);
                      if (t->empty()) {
                            qDebug("read empty text");
                            }
                      else
                            add(t);
                      }
                }
          else if (tag == "Symbol") {
                Symbol* s = new Symbol(score());
                s->read(e);
                add(s);
                }
          else if (tag == "Image") {
                if (MScore::noImages)
                      e.skipCurrentElement();
                else {
                      Image* image = new Image(score());
                      image->setTrack(e.track());
                      image->read(e);
                      add(image);
                      }
                }
          else if (tag == "FretDiagram") {
                FretDiagram* f = new FretDiagram(score());
                f->read(e);
                add(f);
                }
          else if (tag == "HBox") {
                HBox* hb = new HBox(score());
                hb->read(e);
                add(hb);
                }
          else if (tag == "VBox") {
                VBox* vb = new VBox(score());
                vb->read(e);
                add(vb);
                }
          else if (MeasureBase::readProperties(e))
                ;
          else
                return false;
          return true;
          }

    //---------------------------------------------------------
    //   add
    ///   Add new Element \a el to Box
    //---------------------------------------------------------

    void Box::add(Element* e)
          {
          if (e->type() == ElementType::TEXT)
                static_cast<Text*>(e)->setLayoutToParentWidth(true);
          MeasureBase::add(e);
          }

    //---------------------------------------------------------
    //   getProperty
    //---------------------------------------------------------

    QVariant Box::getProperty(P_ID propertyId) const
          {
          switch(propertyId) {
                case P_ID::BOX_HEIGHT:
                      return _boxHeight;
                case P_ID::BOX_WIDTH:
                      return _boxWidth;
                case P_ID::TOP_GAP:
                      return _topGap;
                case P_ID::BOTTOM_GAP:
                      return _bottomGap;
                case P_ID::LEFT_MARGIN:
                      return _leftMargin;
                case P_ID::RIGHT_MARGIN:
                      return _rightMargin;
                case P_ID::TOP_MARGIN:
                      return _topMargin;
                case P_ID::BOTTOM_MARGIN:
                      return _bottomMargin;
                default:
                      return MeasureBase::getProperty(propertyId);
                }
          }

    //---------------------------------------------------------
    //   setProperty
    //---------------------------------------------------------

    bool Box::setProperty(P_ID propertyId, const QVariant& v)
          {
          score()->addRefresh(canvasBoundingRect());
          switch(propertyId) {
                case P_ID::BOX_HEIGHT:
                      _boxHeight = v.value<Spatium>();
                      break;
                case P_ID::BOX_WIDTH:
                      _boxWidth = v.value<Spatium>();
                      break;
                case P_ID::TOP_GAP:
                      _topGap = v.toDouble();
                      topGapStyle = PropertyFlags::UNSTYLED;
                      break;
                case P_ID::BOTTOM_GAP:
                      _bottomGap = v.toDouble();
                      bottomGapStyle = PropertyFlags::UNSTYLED;
                      break;
                case P_ID::LEFT_MARGIN:
                      _leftMargin = v.toDouble();
                      break;
                case P_ID::RIGHT_MARGIN:
                      _rightMargin = v.toDouble();
                      break;
                case P_ID::TOP_MARGIN:
                      _topMargin = v.toDouble();
                      break;
                case P_ID::BOTTOM_MARGIN:
                      _bottomMargin = v.toDouble();
                      break;
                default:
                      return MeasureBase::setProperty(propertyId, v);
                }
          score()->setLayout(tick());
          return true;
          }

    //---------------------------------------------------------
    //   propertyDefault
    //---------------------------------------------------------

    QVariant Box::propertyDefault(P_ID id) const
          {
          switch(id) {
                case P_ID::BOX_HEIGHT:
                case P_ID::BOX_WIDTH:
                      return Spatium(0.0);

                case P_ID::TOP_GAP:
                      return isHBox() ? 0.0 : score()->styleP(StyleIdx::systemFrameDistance);
                case P_ID::BOTTOM_GAP:
                      return isHBox() ? 0.0 : score()->styleP(StyleIdx::frameSystemDistance);

                case P_ID::LEFT_MARGIN:
                case P_ID::RIGHT_MARGIN:
                case P_ID::TOP_MARGIN:
                case P_ID::BOTTOM_MARGIN:
                      return 0.0;
                default:
                      return MeasureBase::propertyDefault(id);
                }
          }

    //---------------------------------------------------------
    //   propertyFlags
    //---------------------------------------------------------

    PropertyFlags Box::propertyFlags(P_ID id) const
          {
          switch (id) {
                case P_ID::TOP_GAP:
                      return topGapStyle;
                case P_ID::BOTTOM_GAP:
                      return bottomGapStyle;
                default:
                      return MeasureBase::propertyFlags(id);
                }
          }

    //---------------------------------------------------------
    //   resetProperty
    //---------------------------------------------------------

    void Box::resetProperty(P_ID id)
          {
          switch (id) {
                case P_ID::TOP_GAP:
                      setTopGap(isHBox() ? 0.0 : score()->styleP(StyleIdx::systemFrameDistance));
                      topGapStyle = PropertyFlags::STYLED;
                      break;
                case P_ID::BOTTOM_GAP:
                      setBottomGap(isHBox() ? 0.0 : score()->styleP(StyleIdx::frameSystemDistance));
                      bottomGapStyle = PropertyFlags::STYLED;
                      break;
                default:
                      return MeasureBase::resetProperty(id);
                }
          score()->setLayout(tick());
          }

    //---------------------------------------------------------
    //   styleChanged
    //    reset all styled values to actual style
    //---------------------------------------------------------

    void Box::styleChanged()
          {
          if (topGapStyle == PropertyFlags::STYLED)
                setTopGap(isHBox() ? 0.0 : score()->styleP(StyleIdx::systemFrameDistance));
          if (bottomGapStyle == PropertyFlags::STYLED)
                setBottomGap(isHBox() ? 0.0 : score()->styleP(StyleIdx::frameSystemDistance));
          score()->setLayout(tick());
          }

    //---------------------------------------------------------
    //   getPropertyStyle
    //---------------------------------------------------------

    StyleIdx Box::getPropertyStyle(P_ID id) const
          {
          switch (id) {
                case P_ID::TOP_GAP:
                      return isHBox() ? StyleIdx::NOSTYLE : StyleIdx::systemFrameDistance;
                case P_ID::BOTTOM_GAP:
                      return isHBox() ? StyleIdx::NOSTYLE : StyleIdx::frameSystemDistance;
                default:
                      break;
                }
          return StyleIdx::NOSTYLE;
          }

    //---------------------------------------------------------
    //   copyValues
    //---------------------------------------------------------

    void Box::copyValues(Box* origin)
          {
          _boxHeight    = origin->boxHeight();
          _boxWidth     = origin->boxWidth();

          qreal factor  = magS() / origin->magS();
          _bottomGap    = origin->bottomGap() * factor;
          _topGap       = origin->topGap() * factor;
          _bottomMargin = origin->bottomMargin() * factor;
          _topMargin    = origin->topMargin() * factor;
          _leftMargin   = origin->leftMargin() * factor;
          _rightMargin  = origin->rightMargin() * factor;
          }

    //---------------------------------------------------------
    //   HBox
    //---------------------------------------------------------

    HBox::HBox(Score* score)
       : Box(score)
          {
          setBoxWidth(Spatium(5.0));
          }

    //---------------------------------------------------------
    //   layout
    //---------------------------------------------------------

    void HBox::layout()
          {
          if (parent() && parent()->type() == ElementType::VBOX) {
                VBox* vb = static_cast<VBox*>(parent());
                qreal x = vb->leftMargin() * DPMM;
                qreal y = vb->topMargin() * DPMM;
                qreal w = point(boxWidth());
                qreal h = vb->height() - (vb->topMargin() + vb->bottomMargin()) * DPMM;
                setPos(x, y);
                bbox().setRect(0.0, 0.0, w, h);
                }
          else {
                bbox().setRect(0.0, 0.0, point(boxWidth()), system()->height());
                }
          Box::layout();
          adjustReadPos();
          }

    //---------------------------------------------------------
    //   layout2
    //    height (bbox) is defined now
    //---------------------------------------------------------

    void HBox::layout2()
          {
          Box::layout();
          }

    //---------------------------------------------------------
    //   acceptDrop
    //---------------------------------------------------------

    bool Box::acceptDrop(EditData& data) const
          {
          ElementType t = data.element->type();
          if (data.element->flag(ElementFlag::ON_STAFF))
                return false;
          switch (t) {
                case ElementType::LAYOUT_BREAK:
                case ElementType::TEXT:
                case ElementType::STAFF_TEXT:
                case ElementType::IMAGE:
                case ElementType::SYMBOL:
                      return true;
                case ElementType::ICON:
                      switch (toIcon(data.element)->iconType()) {
                            case IconType::VFRAME:
                            case IconType::TFRAME:
                            case IconType::FFRAME:
                            case IconType::MEASURE:
                                  return true;
                            default:
                                  break;
                            }
                      break;
                case ElementType::BAR_LINE:
                      return type() == ElementType::HBOX;
                default:
                      break;
                }
          return false;
          }

    //---------------------------------------------------------
    //   drop
    //---------------------------------------------------------

    Element* Box::drop(EditData& data)
          {
          Element* e = data.element;
          if (e->flag(ElementFlag::ON_STAFF))
                return 0;
          switch (e->type()) {
                case ElementType::LAYOUT_BREAK:
                      {
                      LayoutBreak* lb = static_cast<LayoutBreak*>(e);
                      if (pageBreak() || lineBreak()) {
                            if (
                               (lb->isPageBreak() && pageBreak())
                               || (lb->isLineBreak() && lineBreak())
                               || (lb->isSectionBreak() && sectionBreak())
                               ) {
                                  //
                                  // if break already set
                                  //
                                  delete lb;
                                  break;
                                  }
                            for (Element* elem : el()) {
                                  if (elem->type() == ElementType::LAYOUT_BREAK) {
                                        score()->undoChangeElement(elem, e);
                                        break;
                                        }
                                  }
                            break;
                            }
                      lb->setTrack(-1);       // these are system elements
                      lb->setParent(this);
                      score()->undoAddElement(lb);
                      return lb;
                      }

                case ElementType::STAFF_TEXT:
                      {
                      Text* text = new Text(SubStyle::FRAME, score());
                      text->setParent(this);
                      text->setXmlText(static_cast<StaffText*>(e)->xmlText());
                      score()->undoAddElement(text);
                      delete e;
                      return text;
                      }

                case ElementType::ICON:
                      switch (toIcon(e)->iconType()) {
                            case IconType::VFRAME:
                                  score()->insertMeasure(ElementType::VBOX, this);
                                  break;
                            case IconType::TFRAME:
                                  score()->insertMeasure(ElementType::TBOX, this);
                                  break;
                            case IconType::FFRAME:
                                  score()->insertMeasure(ElementType::FBOX, this);
                                  break;
                            case IconType::MEASURE:
                                  score()->insertMeasure(ElementType::MEASURE, this);
                                  break;
                            default:
                                  break;
                            }
                      break;

                case ElementType::TEXT:
                case ElementType::IMAGE:
                case ElementType::SYMBOL:
                      e->setParent(this);
                      score()->undoAddElement(e);
                      return e;
    #if 0
                case ElementType::BAR_LINE: {
                      MeasureBase* mb = next();
                      if (!mb || !mb->isMeasure()) {
                            delete e;
                            return 0;
                            }
                      score()->undoChangeBarLine(toMeasure(mb), toBarLine(e)->barLineType(), true);
                      }
                      return 0;
    #endif
                default:
                      return 0;
                }
          return 0;
          }

    //---------------------------------------------------------
    //   drag
    //---------------------------------------------------------

    QRectF HBox::drag(EditData& data)
          {
          QRectF r(canvasBoundingRect());
          qreal diff = data.delta.x();
          qreal x1   = userOff().x() + diff;
          if (parent()->type() == ElementType::VBOX) {
                VBox* vb = static_cast<VBox*>(parent());
                qreal x2 = parent()->width() - width() - (vb->leftMargin() + vb->rightMargin()) * DPMM;
                if (x1 < 0.0)
                      x1 = 0.0;
                else if (x1 > x2)
                      x1 = x2;
                }
          setUserOff(QPointF(x1, 0.0));
    //      setStartDragPosition(data.delta);
          return canvasBoundingRect() | r;
          }

    //---------------------------------------------------------
    //   endEditDrag
    //---------------------------------------------------------

    void HBox::endEditDrag(EditData&)
          {
          score()->setLayout(tick());
          score()->update();
          }

    //---------------------------------------------------------
    //   isMovable
    //---------------------------------------------------------

    bool HBox::isMovable() const
          {
          return parent() && (parent()->isHBox() || parent()->isVBox());
          }

    //---------------------------------------------------------
    //   getProperty
    //---------------------------------------------------------

    QVariant HBox::getProperty(P_ID propertyId) const
          {
          switch (propertyId) {
                case P_ID::CREATE_SYSTEM_HEADER:
                      return createSystemHeader();
                default:
                      return Box::getProperty(propertyId);
                }
          }

    //---------------------------------------------------------
    //   setProperty
    //---------------------------------------------------------

    bool HBox::setProperty(P_ID propertyId, const QVariant& v)
          {
          switch (propertyId) {
                case P_ID::CREATE_SYSTEM_HEADER:
                      setCreateSystemHeader(v.toBool());
                      score()->setLayout(tick());
                      break;
                default:
                      return Box::setProperty(propertyId, v);
                }
          return true;
          }

    //---------------------------------------------------------
    //   propertyDefault
    //---------------------------------------------------------

    QVariant HBox::propertyDefault(P_ID id) const
          {
          switch(id) {
                case P_ID::CREATE_SYSTEM_HEADER:
                      return true;
                default:
                      return Box::propertyDefault(id);
                }
          }

    //---------------------------------------------------------
    //   VBox
    //---------------------------------------------------------

    VBox::VBox(Score* score)
       : Box(score)
          {
          setBoxHeight(Spatium(10.0));
          setTopGap(score->styleP(StyleIdx::systemFrameDistance));
          setBottomGap(score->styleP(StyleIdx::frameSystemDistance));
          setLineBreak(true);
          }

    //---------------------------------------------------------
    //   layout
    //---------------------------------------------------------

    void VBox::layout()
          {
          setPos(QPointF());      // !?
          if (system())
                bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
          else
                bbox().setRect(0.0, 0.0, 50, 50);
          Box::layout();
          }

    //---------------------------------------------------------
    //   layout
    //---------------------------------------------------------

    void FBox::layout()
          {
    //      setPos(QPointF());      // !?
          bbox().setRect(0.0, 0.0, system()->width(), point(boxHeight()));
          Box::layout();
          }

    //---------------------------------------------------------
    //   add
    ///   Add new Element \a e to fret diagram box
    //---------------------------------------------------------

    void FBox::add(Element* e)
          {
          e->setParent(this);
          if (e->type() == ElementType::FRET_DIAGRAM) {
    //            FretDiagram* fd = static_cast<FretDiagram*>(e);
    //            fd->setFlag(ElementFlag::MOVABLE, false);
                }
          else {
                qDebug("FBox::add: element not allowed");
                return;
                }
          el().push_back(e);
          }

    }

↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: dragX.