Skip to content

Commit

Permalink
Merge pull request #5763 from dmitrio95/anchors_rebasing
Browse files Browse the repository at this point in the history
Rebase segment-anchored lines on dragging
  • Loading branch information
anatoly-os authored Apr 17, 2020
2 parents 9c614db + c026ade commit f993cc2
Show file tree
Hide file tree
Showing 30 changed files with 1,001 additions and 204 deletions.
4 changes: 2 additions & 2 deletions libmscore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ add_library (
fermata.cpp articulation.cpp barline.cpp beam.cpp bend.cpp box.cpp
bracket.cpp breath.cpp bsp.cpp changeMap.cpp chord.cpp chordline.cpp
chordlist.cpp chordrest.cpp clef.cpp cleflist.cpp
drumset.cpp durationtype.cpp dynamic.cpp edit.cpp noteentry.cpp
element.cpp excerpt.cpp
drumset.cpp durationtype.cpp dynamic.cpp dynamichairpingroup.cpp edit.cpp noteentry.cpp
element.cpp elementgroup.cpp excerpt.cpp
fifo.cpp fret.cpp glissando.cpp hairpin.cpp
harmony.cpp hook.cpp image.cpp iname.cpp instrchange.cpp
instrtemplate.cpp instrument.cpp interval.cpp
Expand Down
2 changes: 1 addition & 1 deletion libmscore/beam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2565,7 +2565,7 @@ void Beam::initBeamEditData(EditData& ed)
bed->editFragment = 0;
ed.addData(bed);

QPointF pt(ed.startMove - pagePos());
QPointF pt(ed.normalizedStartMove - pagePos());
qreal ydiff = 100000000.0;
int idx = (_direction == Direction::AUTO || _direction == Direction::DOWN) ? 0 : 1;
int i = 0;
Expand Down
2 changes: 1 addition & 1 deletion libmscore/box.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ Element* Box::drop(EditData& data)
QRectF HBox::drag(EditData& data)
{
QRectF r(canvasBoundingRect());
qreal diff = data.delta.x();
qreal diff = data.evtDelta.x();
qreal x1 = offset().x() + diff;
if (parent()->type() == ElementType::VBOX) {
VBox* vb = toVBox(parent());
Expand Down
23 changes: 20 additions & 3 deletions libmscore/dynamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//=============================================================================

#include "dynamic.h"
#include "dynamichairpingroup.h"
#include "xml.h"
#include "score.h"
#include "measure.h"
Expand Down Expand Up @@ -344,6 +345,19 @@ void Dynamic::reset()
TextBase::reset();
}

//---------------------------------------------------------
// getDragGroup
//---------------------------------------------------------

std::unique_ptr<ElementGroup> Dynamic::getDragGroup(std::function<bool(const Element*)> isDragged)
{
if (auto g = HairpinWithDynamicsDragGroup::detectFor(this, isDragged))
return g;
if (auto g = DynamicNearHairpinsDragGroup::detectFor(this, isDragged))
return g;
return TextBase::getDragGroup(isDragged);
}

//---------------------------------------------------------
// drag
//---------------------------------------------------------
Expand All @@ -359,15 +373,18 @@ QRectF Dynamic::drag(EditData& ed)
if (km != (Qt::ShiftModifier | Qt::ControlModifier)) {
int si = staffIdx();
Segment* seg = segment();
score()->dragPosition(ed.pos, &si, &seg);
score()->dragPosition(canvasPos(), &si, &seg);
if (seg != segment() || staffIdx() != si) {
const QPointF oldOffset = offset();
QPointF pos1(canvasPos());
score()->undo(new ChangeParent(this, seg, si));
setOffset(QPointF());
layout();
QPointF pos2(canvasPos());
setOffset(pos1 - pos2);
ed.startMove = pos2;
const QPointF newOffset = pos1 - pos2;
setOffset(newOffset);
ElementEditData* eed = ed.getData(this);
eed->initOffset += newOffset - oldOffset;
}
}
return f;
Expand Down
2 changes: 2 additions & 0 deletions libmscore/dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ class Dynamic final : public TextBase {
Pid propertyId(const QStringRef& xmlName) const override;
QString propertyUserValue(Pid) const override;

std::unique_ptr<ElementGroup> getDragGroup(std::function<bool(const Element*)> isDragged) override;

QString accessibleInfo() const override;
QString screenReaderInfo() const override;
void doAutoplace();
Expand Down
190 changes: 190 additions & 0 deletions libmscore/dynamichairpingroup.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA
//
// 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 "dynamichairpingroup.h"
#include "dynamic.h"
#include "hairpin.h"
#include "score.h"
#include "segment.h"

namespace Ms {

static std::pair<Hairpin*, Hairpin*> findAdjacentHairpins(Dynamic* d)
{
Score* score = d->score();
const Segment* dSeg = d->segment();
Hairpin* leftHairpin = nullptr;
Hairpin* rightHairpin = nullptr;

const Fraction tick = dSeg->tick();
const int intTick = tick.ticks();

const auto& nearSpanners = score->spannerMap().findOverlapping(intTick - 1, intTick + 1);
for (auto i : nearSpanners) {
Spanner* s = i.value;
if (s->track() == d->track() && s->isHairpin()) {
Hairpin* h = toHairpin(s);
if (h->tick() == tick)
rightHairpin = h;
else if (h->tick2() == tick)
leftHairpin = h;
}
}

return { leftHairpin, rightHairpin };
}

std::unique_ptr<ElementGroup> HairpinWithDynamicsDragGroup::detectFor(HairpinSegment* hs, std::function<bool(const Element*)> isDragged)
{
if (!hs->isSingleType())
return nullptr;

Hairpin* hairpin = hs->hairpin();

Segment* startSegment = hairpin->startSegment();
Segment* endSegment = hairpin->endSegment();
const int track = hs->track();

Dynamic* startDynamic = toDynamic(startSegment->findAnnotation(ElementType::DYNAMIC, track, track));
Dynamic* endDynamic = toDynamic(endSegment->findAnnotation(ElementType::DYNAMIC, track, track));

// Include only dragged dynamics to this group
if (!isDragged(startDynamic))
startDynamic = nullptr;
if (!isDragged(endDynamic))
endDynamic = nullptr;

if (startDynamic || endDynamic)
return std::unique_ptr<ElementGroup>(new HairpinWithDynamicsDragGroup(startDynamic, hs, endDynamic));
return nullptr;
}

std::unique_ptr<ElementGroup> HairpinWithDynamicsDragGroup::detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged)
{
Hairpin* leftHairpin = nullptr;
Hairpin* rightHairpin = nullptr;

std::tie(leftHairpin, rightHairpin) = findAdjacentHairpins(d);

// Dynamic will be governed bt HairpinWithDynamicsDragGroup if any of adjacent
// hairpins is dragged, disable separate drag logic for dynamic in this case.
if (isDragged(leftHairpin))
return std::unique_ptr<ElementGroup>(new DisabledElementGroup());
if (isDragged(rightHairpin))
return std::unique_ptr<ElementGroup>(new DisabledElementGroup());

return nullptr;
}

void HairpinWithDynamicsDragGroup::startDrag(EditData& ed)
{
if (startDynamic)
startDynamic->startDrag(ed);
static_cast<Element*>(hairpinSegment)->startDrag(ed);
if (endDynamic)
endDynamic->startDrag(ed);
}

QRectF HairpinWithDynamicsDragGroup::drag(EditData& ed)
{
QRectF r;

if (startDynamic)
r |= static_cast<Element*>(startDynamic)->drag(ed);
r |= hairpinSegment->drag(ed);
if (endDynamic)
r |= static_cast<Element*>(endDynamic)->drag(ed);

Hairpin* h = hairpinSegment->hairpin();

const Fraction startTick = startDynamic ? startDynamic->segment()->tick() : h->tick();
const Fraction endTick = endDynamic ? endDynamic->segment()->tick() : h->tick2();

if (endTick > startTick) {
if (h->tick() != startTick)
h->undoChangeProperty(Pid::SPANNER_TICK, startTick);
if (h->tick2() != endTick)
h->undoChangeProperty(Pid::SPANNER_TICKS, endTick - startTick);
}

return r;
}

void HairpinWithDynamicsDragGroup::endDrag(EditData& ed)
{
if (startDynamic) {
startDynamic->endDrag(ed);
startDynamic->triggerLayout();
}

hairpinSegment->endDrag(ed);
hairpinSegment->triggerLayout();

if (endDynamic) {
endDynamic->endDrag(ed);
endDynamic->triggerLayout();
}
}

std::unique_ptr<ElementGroup> DynamicNearHairpinsDragGroup::detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged)
{
Hairpin* leftHairpin = nullptr;
Hairpin* rightHairpin = nullptr;

std::tie(leftHairpin, rightHairpin) = findAdjacentHairpins(d);

// Drag hairpins according to this rule only if they are not being dragged themselves
if (isDragged(leftHairpin))
leftHairpin = nullptr;
if (isDragged(rightHairpin))
rightHairpin = nullptr;

if (leftHairpin || rightHairpin)
return std::unique_ptr<ElementGroup>(new DynamicNearHairpinsDragGroup(leftHairpin, d, rightHairpin));
return nullptr;
}

void DynamicNearHairpinsDragGroup::startDrag(EditData& ed)
{
dynamic->startDrag(ed);
}

QRectF DynamicNearHairpinsDragGroup::drag(EditData& ed)
{
QRectF r(static_cast<Element*>(dynamic)->drag(ed));

const Fraction tick = dynamic->segment()->tick();

if (leftHairpin && leftHairpin->tick2() != tick && tick > leftHairpin->tick())
leftHairpin->undoChangeProperty(Pid::SPANNER_TICKS, tick - leftHairpin->tick());

if (rightHairpin && rightHairpin->tick() != tick) {
const Fraction tick2 = rightHairpin->tick2();
if (tick < tick2) {
rightHairpin->undoChangeProperty(Pid::SPANNER_TICK, tick);
rightHairpin->undoChangeProperty(Pid::SPANNER_TICKS, tick2 - tick);
}
}

if (leftHairpin || rightHairpin)
dynamic->triggerLayout();

return r;
}

void DynamicNearHairpinsDragGroup::endDrag(EditData& ed)
{
dynamic->endDrag(ed);
dynamic->triggerLayout();
}

} // namespace Ms
68 changes: 68 additions & 0 deletions libmscore/dynamichairpingroup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA
//
// 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
//=============================================================================

#ifndef __DYNAMICHAIPRINGROUP_H__
#define __DYNAMICHAIRPINGROUP_H__

#include "elementgroup.h"

namespace Ms {

class Dynamic;
class Hairpin;
class HairpinSegment;

//-------------------------------------------------------------------
// HairpinWithDynamicsDragGroup
/// Sequence of Dynamics and Hairpins
//-------------------------------------------------------------------

class HairpinWithDynamicsDragGroup : public ElementGroup {
Dynamic* startDynamic;
HairpinSegment* hairpinSegment;
Dynamic* endDynamic;

public:
HairpinWithDynamicsDragGroup(Dynamic* start, HairpinSegment* hs, Dynamic* end)
: startDynamic(start), hairpinSegment(hs), endDynamic(end) {}

void startDrag(EditData&) override;
QRectF drag(EditData&) override;
void endDrag(EditData&) override;

static std::unique_ptr<ElementGroup> detectFor(HairpinSegment* hs, std::function<bool(const Element*)> isDragged);
static std::unique_ptr<ElementGroup> detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged);
};

//-------------------------------------------------------------------
// DynamicNearHairpinsDragGroup
//-------------------------------------------------------------------

class DynamicNearHairpinsDragGroup : public ElementGroup {
Hairpin* leftHairpin;
Dynamic* dynamic;
Hairpin* rightHairpin;

public:
DynamicNearHairpinsDragGroup(Hairpin* left, Dynamic* d, Hairpin* right)
: leftHairpin(left), dynamic(d), rightHairpin(right) {}

void startDrag(EditData&) override;
QRectF drag(EditData&) override;
void endDrag(EditData&) override;

static std::unique_ptr<ElementGroup> detectFor(Dynamic* d, std::function<bool(const Element*)> isDragged);
};

} // namespace Ms

#endif
8 changes: 6 additions & 2 deletions libmscore/element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1946,6 +1946,7 @@ void Element::startDrag(EditData& ed)
eed->e = this;
eed->pushProperty(Pid::OFFSET);
eed->pushProperty(Pid::AUTOPLACE);
eed->initOffset = offset();
ed.addData(eed);
if (ed.modifiers & Qt::AltModifier)
setAutoplace(false);
Expand All @@ -1963,8 +1964,11 @@ QRectF Element::drag(EditData& ed)

const QRectF r0(canvasBoundingRect());

qreal x = ed.delta.x();
qreal y = ed.delta.y();
const ElementEditData* eed = ed.getData(this);

const QPointF offset0 = ed.moveDelta + eed->initOffset;
qreal x = offset0.x();
qreal y = offset0.y();

qreal _spatium = spatium();
if (ed.hRaster) {
Expand Down
Loading

0 comments on commit f993cc2

Please sign in to comment.