Skip to content
28 changes: 27 additions & 1 deletion src/plugins/score-lib-process/Process/Dataflow/NodeItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <score/graphics/GraphicsLayout.hpp>
#include <score/graphics/TextItem.hpp>
#include <score/model/Skin.hpp>
#include <score/selection/Selection.hpp>
#include <score/selection/SelectionDispatcher.hpp>
#include <score/selection/SelectionStack.hpp>
#include <score/tools/Bind.hpp>
Expand Down Expand Up @@ -941,6 +942,8 @@ enum Interaction
} nodeItemInteraction{};
QSizeF origNodeSize{};
bool nodeDidMove{};
bool nodeSelectOnRelease{};
bool nodeSelectCumulation{};
}

void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
Expand All @@ -963,7 +966,21 @@ void NodeItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
m_context.focusDispatcher.focus(m_presenter);
}
score::SelectionDispatcher{m_context.selectionStack}.select(m_model);
{
const bool cumulation = event->modifiers() & Qt::ControlModifier;
if(m_model.selection.get())
{
nodeSelectOnRelease = true;
nodeSelectCumulation = cumulation;
}
else
{
nodeSelectOnRelease = false;
Selection sel = filterSelections(
&m_model, m_context.selectionStack.currentSelection(), cumulation);
score::SelectionDispatcher{m_context.selectionStack}.select(sel);
}
}
event->accept();
}
else
Expand Down Expand Up @@ -1028,7 +1045,16 @@ void NodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
mouseMoveEvent(event);

if(nodeDidMove)
{
m_dispatcher.commit<Process::MoveNodesMacro>();
}
else if(nodeSelectOnRelease)
{
Selection sel = filterSelections(
&m_model, m_context.selectionStack.currentSelection(), nodeSelectCumulation);
score::SelectionDispatcher{m_context.selectionStack}.select(sel);
}
nodeSelectOnRelease = false;
nodeDidMove = false;
event->accept();
}
Expand Down
17 changes: 17 additions & 0 deletions src/plugins/score-plugin-nodal/Nodal/Presenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <score/command/Dispatchers/CommandDispatcher.hpp>
#include <score/command/Dispatchers/MacroCommandDispatcher.hpp>
#include <score/model/EntitySerialization.hpp>
#include <score/selection/Selection.hpp>
#include <score/selection/SelectionDispatcher.hpp>
#include <score/selection/SelectionStack.hpp>
#include <score/tools/Bind.hpp>

#include <ossia/detail/math.hpp>
Expand All @@ -31,6 +34,7 @@ Presenter::Presenter(
bind(layer.nodes, *this);

connect(view, &View::dropReceived, this, &Presenter::on_drop);
connect(view, &View::areaSelectRequested, this, &Presenter::on_areaSelect);

if(auto itv = Scenario::closestParentInterval(m_model.parent()))
{
Expand Down Expand Up @@ -154,4 +158,17 @@ void Presenter::on_removing(const Process::ProcessModel& n)
{
m_nodes.erase(n.id());
}

void Presenter::on_areaSelect(QRectF rect, bool cumulation)
{
Selection sel;
for(Process::NodeItem& node : m_nodes)
{
const QRectF nodeRect = m_view->mapRectFromScene(node.sceneBoundingRect());
if(rect.intersects(nodeRect))
sel.append(node.model());
}
sel = filterSelections(sel, m_context.context.selectionStack.currentSelection(), cumulation);
score::SelectionDispatcher{m_context.context.selectionStack}.select(sel);
}
}
4 changes: 4 additions & 0 deletions src/plugins/score-plugin-nodal/Nodal/Presenter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <Nodal/Process.hpp>

#include <score/model/Identifier.hpp>

#include <QRectF>

namespace Nodal
{
class Model;
Expand All @@ -33,6 +36,7 @@ class Presenter final
void on_created(Process::ProcessModel& n);
void on_removing(const Process::ProcessModel& n);
void on_drop(const QPointF& pos, const QMimeData& mime);
void on_areaSelect(QRectF rect, bool cumulation);

private:
IdContainer<Process::NodeItem, Process::ProcessModel> m_nodes;
Expand Down
67 changes: 66 additions & 1 deletion src/plugins/score-plugin-nodal/Nodal/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,87 @@

#include <Process/Style/ScenarioStyle.hpp>

#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>

#include <wobjectimpl.h>
W_OBJECT_IMPL(Nodal::View)

namespace Nodal
{

View::View(QGraphicsItem* parent)
: LayerView{parent}
{
setFlag(ItemHasNoContents, true);
setFlag(ItemClipsChildrenToShape);

{
auto selColor = score::Skin::instance().Base2.darker.brush.color();
auto selFill = selColor;
selFill.setAlpha(40);
m_selectionRect = new QGraphicsRectItem(this);
m_selectionRect->setZValue(1000.);
m_selectionRect->setPen(QPen{selColor, 1, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin});
m_selectionRect->setBrush(selFill);
m_selectionRect->setAcceptedMouseButtons(Qt::NoButton);
m_selectionRect->setVisible(false);
}
}

View::~View() { }

void View::paint_impl(QPainter* painter) const { }

void View::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
if(event->button() == Qt::LeftButton && (event->modifiers() & Qt::ControlModifier))
{
m_rubberBanding = true;
m_rubberBandOrigin = event->pos();
m_rubberBandRect = QRectF{m_rubberBandOrigin, m_rubberBandOrigin};
m_selectionRect->setVisible(true);
m_selectionRect->setRect(QRectF{});
event->accept();
}
else
{
LayerView::mousePressEvent(event);
}
}

void View::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if(m_rubberBanding && (event->buttons() & Qt::LeftButton))
{
m_rubberBandRect = QRectF{m_rubberBandOrigin, event->pos()}.normalized();
m_selectionRect->setRect(m_rubberBandRect);
event->accept();
}
else
{
LayerView::mouseMoveEvent(event);
}
}

void View::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if(event->button() == Qt::LeftButton && m_rubberBanding)
{
m_rubberBanding = false;
m_selectionRect->setVisible(false);
m_selectionRect->setRect(QRectF{});
const bool cumulation = event->modifiers() & Qt::ControlModifier;
areaSelectRequested(m_rubberBandRect, cumulation);
m_rubberBandRect = {};
event->accept();
}
else
{
LayerView::mouseReleaseEvent(event);
}
}

void View::dragEnterEvent(QGraphicsSceneDragDropEvent* event) { }

void View::dragLeaveEvent(QGraphicsSceneDragDropEvent* event) { }
Expand Down
22 changes: 22 additions & 0 deletions src/plugins/score-plugin-nodal/Nodal/View.hpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
#pragma once
#include <Process/LayerView.hpp>

#include <QPointF>
#include <QRectF>

class QGraphicsRectItem;

#include <score_plugin_nodal_export.h>

#include <verdigris>

namespace Nodal
{
class View final : public Process::LayerView
{
W_OBJECT(View)
public:
explicit View(QGraphicsItem* parent);
~View() override;

void areaSelectRequested(QRectF area, bool cumulation)
E_SIGNAL(SCORE_PLUGIN_NODAL_EXPORT, areaSelectRequested, area, cumulation)

private:
void paint_impl(QPainter*) const override;

void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;

void dragEnterEvent(QGraphicsSceneDragDropEvent* event) override;
void dragLeaveEvent(QGraphicsSceneDragDropEvent* event) override;
void dragMoveEvent(QGraphicsSceneDragDropEvent* event) override;
void dropEvent(QGraphicsSceneDragDropEvent* event) override;

QGraphicsRectItem* m_selectionRect{};
QPointF m_rubberBandOrigin{};
QRectF m_rubberBandRect{};
bool m_rubberBanding{false};
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,11 @@ class RemoveProcessAndKeepLinked final : public score::AggregateCommand
SCORE_COMMAND_DECL(
CommandFactoryName(), RemoveProcessAndKeepLinked, "Remove process from chain")
};

class RemoveMultipleProcessesFromInterval final : public score::AggregateCommand
{
SCORE_COMMAND_DECL(
CommandFactoryName(), RemoveMultipleProcessesFromInterval, "Remove processes")
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@
#include <score/application/GUIApplicationContext.hpp>
#include <score/graphics/GraphicsItem.hpp>
#include <score/graphics/ZoomItem.hpp>
#include <score/model/Skin.hpp>
#include <score/selection/Selection.hpp>
#include <score/selection/SelectionDispatcher.hpp>
#include <score/selection/SelectionStack.hpp>
#include <score/tools/Bind.hpp>

#include <ossia/detail/math.hpp>

#include <QGraphicsRectItem>
#include <QGraphicsSceneDragDropEvent>
#include <QGraphicsView>
#include <QPainter>
#include <QTimer>

#include <wobjectimpl.h>
Expand Down Expand Up @@ -112,6 +116,18 @@ NodalIntervalView::NodalIntervalView(
}

QTimer::singleShot(1, this, &NodalIntervalView::recenterRelativeToView);

{
auto selColor = score::Skin::instance().Base2.darker.brush.color();
auto selFill = selColor;
selFill.setAlpha(40);
m_selectionRect = new QGraphicsRectItem(this);
m_selectionRect->setZValue(1000.);
m_selectionRect->setPen(QPen{selColor, 1, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin});
m_selectionRect->setBrush(selFill);
m_selectionRect->setAcceptedMouseButtons(Qt::NoButton);
m_selectionRect->setVisible(false);
}
}

void NodalIntervalView::zoomPlus()
Expand Down Expand Up @@ -316,37 +332,73 @@ void NodalIntervalView::dropEvent(QGraphicsSceneDragDropEvent* event)

void NodalIntervalView::mousePressEvent(QGraphicsSceneMouseEvent* e)
{
this->m_context.selectionStack.deselect();
auto focus = Process::ProcessFocusManager::get(this->m_context);
focus->focusNothing();

m_pressedPos = e->scenePos();
if(e->button() == Qt::LeftButton)
{
if(e->modifiers() & Qt::ControlModifier)
{
m_rubberBanding = true;
m_rubberBandOrigin = e->pos();
m_rubberBandRect = QRectF{m_rubberBandOrigin, m_rubberBandOrigin};
m_selectionRect->setVisible(true);
m_selectionRect->setRect(QRectF{});
}
else
{
this->m_context.selectionStack.deselect();
auto focus = Process::ProcessFocusManager::get(this->m_context);
if(focus)
focus->focusNothing();
m_pressedPos = e->scenePos();
}
}
else if(e->button() == Qt::MiddleButton)
{
m_pressedPos = e->scenePos();
}
e->accept();

score::SelectionDispatcher disp{m_context.selectionStack};
disp.select(m_model);
}

void NodalIntervalView::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
{
const auto delta = e->scenePos() - m_pressedPos;
m_container->setPos(m_container->pos() + delta);
m_pressedPos = e->scenePos();
if(m_rubberBanding && (e->buttons() & Qt::LeftButton))
{
m_rubberBandRect = QRectF{m_rubberBandOrigin, e->pos()}.normalized();
m_selectionRect->setRect(m_rubberBandRect);
}
else if(e->buttons() & (Qt::LeftButton | Qt::MiddleButton))
{
const auto delta = e->scenePos() - m_pressedPos;
m_container->setPos(m_container->pos() + delta);
m_pressedPos = e->scenePos();
const_cast<IntervalModel&>(m_model).setNodalOffset(m_model.nodalOffset() + delta);
}
e->accept();
const_cast<IntervalModel&>(m_model).setNodalOffset(m_model.nodalOffset() + delta);
}

void NodalIntervalView::mouseReleaseEvent(QGraphicsSceneMouseEvent* e)
{
const auto delta = e->scenePos() - m_pressedPos;
if(e->button() == Qt::LeftButton && m_rubberBanding)
{
m_rubberBanding = false;
m_selectionRect->setVisible(false);
m_selectionRect->setRect(QRectF{});

m_container->setPos(m_container->pos() + delta);
m_pressedPos = e->scenePos();
const bool cumulation = e->modifiers() & Qt::ControlModifier;
Selection sel;
for(auto* node : m_nodeItems)
{
const QRectF nodeRect = mapRectFromScene(node->sceneBoundingRect());
if(m_rubberBandRect.intersects(nodeRect))
sel.append(node->model());
}
sel = filterSelections(sel, m_context.selectionStack.currentSelection(), cumulation);
score::SelectionDispatcher{m_context.selectionStack}.select(sel);
m_rubberBandRect = {};
}
e->accept();

const_cast<IntervalModel&>(m_model).setNodalOffset(m_model.nodalOffset() + delta);
}


void NodalIntervalView::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
event->accept();
Expand Down
Loading
Loading