Display visual feedback of where cards will go (#5737)

This is part of the code from #4974, including an improved drag-and-drop
API and its use to display visual feedback of card destination on the
board.

It does not include the improved logic for pushing cards around as I
still need to figure out edge cases there - the logic for choosing where
cards go is not changed, so some of the artifacts described in #4817
and #4975 (particularly around multi-card) are still present.
This commit is contained in:
Basile Clement 2025-03-17 00:19:39 +01:00 committed by GitHub
parent bd28e04635
commit a7641a571f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 230 additions and 100 deletions

View file

@ -118,9 +118,66 @@ void TableZone::addCardImpl(CardItem *card, int _x, int _y)
card->update();
}
bool TableZone::dragEnter(CardDragItem *dragItem, const QPointF &pos)
{
if (!SelectZone::dragEnter(dragItem, pos)) {
return false;
}
if (m_feedbackItem) {
scene()->removeItem(m_feedbackItem);
delete m_feedbackItem;
}
m_feedbackItem = new QGraphicsPathItem(dragItem->getItem()->shape(), this);
m_feedbackItem->setBrush(QColor(176, 196, 222)); // lightsteelblue
m_feedbackItem->setPen(QColor(119, 136, 153)); // lightslategray
m_feedbackItem->setZValue(2000000005);
m_feedbackItem->setTransform(dragItem->getItem()->transform());
updateFeedback(dragItem, pos);
return true;
}
void TableZone::dragMove(CardDragItem *dragItem, const QPointF &pos)
{
if (m_feedbackItem) {
updateFeedback(dragItem, pos);
}
SelectZone::dragMove(dragItem, pos);
}
void TableZone::dragAccept(CardDragItem *dragItem, const QPointF &pos)
{
SelectZone::dragAccept(dragItem, pos);
if (m_feedbackItem) {
scene()->removeItem(m_feedbackItem);
delete m_feedbackItem;
m_feedbackItem = nullptr;
}
}
void TableZone::dragLeave(CardDragItem *dragItem)
{
SelectZone::dragLeave(dragItem);
if (m_feedbackItem) {
scene()->removeItem(m_feedbackItem);
delete m_feedbackItem;
m_feedbackItem = nullptr;
}
}
void TableZone::handleDropEvent(const QList<CardDragItem *> &dragItems, CardZone *startZone, const QPoint &dropPoint)
{
handleDropEventByGrid(dragItems, startZone, mapToGrid(dropPoint));
Q_UNUSED(dropPoint);
// Always use the position of the feedback item for consistency
if (m_feedbackItem && m_feedbackItem->isVisible()) {
handleDropEventByGrid(dragItems, startZone, mapToGrid(m_feedbackItem->pos()));
}
}
void TableZone::handleDropEventByGrid(const QList<CardDragItem *> &dragItems,
@ -260,12 +317,6 @@ CardItem *TableZone::getCardFromGrid(const QPoint &gridPoint) const
return 0;
}
CardItem *TableZone::getCardFromCoords(const QPointF &point) const
{
QPoint gridPoint = mapToGrid(point);
return getCardFromGrid(gridPoint);
}
void TableZone::computeCardStackWidths()
{
// Each card stack is three grid points worth of card locations.
@ -366,18 +417,36 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const
int xDiff = x - xStack;
int gridPointX = stackCol * 3 + qMin(xDiff / STACKED_CARD_OFFSET_X, 2);
return QPoint(gridPointX, gridPointY);
return QPoint((gridPointX / 3) * 3, gridPointY);
}
QPointF TableZone::closestGridPoint(const QPointF &point)
void TableZone::updateFeedback(CardDragItem *dragItem, const QPointF &point)
{
QPoint gridPoint = mapToGrid(point);
gridPoint.setX((gridPoint.x() / 3) * 3);
if (getCardFromGrid(gridPoint))
gridPoint.setX(gridPoint.x() + 1);
if (getCardFromGrid(gridPoint))
gridPoint.setX(gridPoint.x() + 1);
return mapFromGrid(gridPoint);
for (int i = 0; i < 3; ++i) {
if (CardItem *existingCard = getCardFromGrid(gridPoint)) {
if (existingCard == dragItem->getItem()) {
// Dropping the card onto its existing position is a no-op, and
// we don't want to display the feedback item, but we don't want
// to display an invalid state either, because that'd be
// confusing.
dragItem->setValid(true);
m_feedbackItem->hide();
return;
}
gridPoint.setX(gridPoint.x() + 1);
} else {
dragItem->setValid(true);
m_feedbackItem->show();
m_feedbackItem->setPos(mapFromGrid(gridPoint));
return;
}
}
dragItem->setValid(false);
m_feedbackItem->hide();
}
int TableZone::clampValidTableRow(const int row)