Commit 7947c3d9 authored by Stefan Majewsky's avatar Stefan Majewsky

Introduce the SelectPieceInteractor (assigned to Ctrl+LMB by default).

This brings feature parity with the previous
QGraphicsSceneMouseEvent-based interaction.

svn path=/trunk/KDE/kdegames/palapeli/; revision=1112608
parent 4a464ddf
......@@ -29,6 +29,7 @@ Palapeli::InteractorManager::InteractorManager(QGraphicsView* view)
{
//create interactors
m_interactors["MovePiece"] = new Palapeli::MovePieceInteractor(view);
m_interactors["SelectPiece"] = new Palapeli::SelectPieceInteractor(view);
m_interactors["MoveViewport"] = new Palapeli::MoveViewportInteractor(view);
m_interactors["ZoomViewport"] = new Palapeli::ZoomViewportInteractor(view);
m_interactors["RubberBand"] = new Palapeli::RubberBandInteractor(view);
......@@ -36,6 +37,7 @@ Palapeli::InteractorManager::InteractorManager(QGraphicsView* view)
//setup triggers (WARNING: the insertion order implements priority)
typedef Palapeli::InteractorTrigger PIT;
m_triggers << qMakePair(PIT("LeftButton;NoModifier"), m_interactors["MovePiece"]);
m_triggers << qMakePair(PIT("LeftButton;ControlModifier"), m_interactors["SelectPiece"]);
m_triggers << qMakePair(PIT("RightButton;NoModifier"), m_interactors["MoveViewport"]);
m_triggers << qMakePair(PIT("wheel:Vertical;NoModifier"), m_interactors["ZoomViewport"]);
m_triggers << qMakePair(PIT("LeftButton;NoModifier"), m_interactors["Constraints"]);
......
......@@ -30,7 +30,16 @@
Palapeli::MovePieceInteractor::MovePieceInteractor(QGraphicsView* view)
: Palapeli::Interactor(Palapeli::MouseInteractor, view)
{
setMetadata(i18n("Move pieces by dragging"), QIcon());
setMetadata(i18nc("Description (used like a name) for a mouse interaction method", "Move pieces by dragging"), QIcon());
}
static QGraphicsItem* findSelectableItemAt(const QPointF& scenePos, QGraphicsScene* scene)
{
QList<QGraphicsItem*> itemsUnderMouse = scene->items(scenePos);
foreach (QGraphicsItem* itemUnderMouse, itemsUnderMouse)
if (itemUnderMouse->flags() && QGraphicsItem::ItemIsSelectable)
return itemUnderMouse;
return 0;
}
bool Palapeli::MovePieceInteractor::acceptMousePosition(const QPoint& pos)
......@@ -40,23 +49,12 @@ bool Palapeli::MovePieceInteractor::acceptMousePosition(const QPoint& pos)
//we are currently moving something -> grab all events
if (!m_currentPieces.isEmpty())
return true;
//find selectable item under mouse
const QPointF scenePos = view()->mapToScene(pos);
QList<QGraphicsItem*> itemsUnderMouse = scene()->items(scenePos);
QGraphicsItem* selectableItemUnderMouse = 0;
foreach (QGraphicsItem* itemUnderMouse, itemsUnderMouse)
{
if (itemUnderMouse->flags() && QGraphicsItem::ItemIsSelectable)
{
selectableItemUnderMouse = itemUnderMouse;
break;
}
}
//no item under mouse -> no interaction possible
QGraphicsItem* selectableItemUnderMouse = findSelectableItemAt(view()->mapToScene(pos), scene());
if (!selectableItemUnderMouse)
return false;
//we will only move pieces -> find the piece which we are moving
Palapeli::Piece* piece = findPieceForItem(selectableItemUnderMouse);
Palapeli::Piece* piece = Palapeli::Piece::fromSelectedItem(selectableItemUnderMouse);
if (!piece)
return false;
//start moving this piece
......@@ -64,13 +62,6 @@ bool Palapeli::MovePieceInteractor::acceptMousePosition(const QPoint& pos)
return true;
}
Palapeli::Piece* Palapeli::MovePieceInteractor::findPieceForItem(QGraphicsItem* mouseInteractingItem) const
{
//try to cast the item and its parent
Palapeli::Piece* piece = qgraphicsitem_cast<Palapeli::Piece*>(mouseInteractingItem);
return piece ? piece : qgraphicsitem_cast<Palapeli::Piece*>(mouseInteractingItem->parentItem());
}
void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clickedItem, Palapeli::Piece* clickedPiece)
{
m_currentItems.clear();
......@@ -81,7 +72,7 @@ void Palapeli::MovePieceInteractor::determineSelectedItems(QGraphicsItem* clicke
//clicked item is already selected -> include all selected items/pieces in this move
foreach (QGraphicsItem* selectedItem, selectedItems)
{
Palapeli::Piece* selectedPiece = findPieceForItem(selectedItem);
Palapeli::Piece* selectedPiece = Palapeli::Piece::fromSelectedItem(selectedItem);
if (selectedPiece)
{
m_currentItems << selectedItem;
......@@ -132,12 +123,41 @@ void Palapeli::MovePieceInteractor::mouseReleaseEvent(const Palapeli::MouseEvent
}
//END Palapeli::MovePieceInteractor
//BEGIN Palapeli::SelectPieceInteractor
Palapeli::SelectPieceInteractor::SelectPieceInteractor(QGraphicsView* view)
: Palapeli::Interactor(Palapeli::MouseInteractor, view)
{
setMetadata(i18nc("Description (used like a name) for a mouse interaction method", "Select pieces by clicking"), QIcon());
}
bool Palapeli::SelectPieceInteractor::acceptMousePosition(const QPoint& pos)
{
if (!scene())
return false;
//no item under mouse -> no interaction possible
QGraphicsItem* selectableItemUnderMouse = findSelectableItemAt(view()->mapToScene(pos), scene());
if (!selectableItemUnderMouse)
return false;
//we will only move pieces -> find the piece which we are moving
m_currentPiece = Palapeli::Piece::fromSelectedItem(selectableItemUnderMouse);
return (bool) m_currentPiece;
}
void Palapeli::SelectPieceInteractor::mousePressEvent(const Palapeli::MouseEvent& event)
{
Q_UNUSED(event)
//toggle selection state for piece under mouse
m_currentPiece->setSelected(!m_currentPiece->isSelected());
}
//END Palapeli::SelectPieceInteractor
//BEGIN Palapeli::MoveViewportInteractor
Palapeli::MoveViewportInteractor::MoveViewportInteractor(QGraphicsView* view)
: Palapeli::Interactor(Palapeli::MouseInteractor, view)
{
setMetadata(i18n("Move viewport by dragging"), QIcon());
setMetadata(i18nc("Description (used like a name) for a mouse interaction method", "Move viewport by dragging"), QIcon());
}
void Palapeli::MoveViewportInteractor::mousePressEvent(const Palapeli::MouseEvent& event)
......@@ -160,7 +180,7 @@ void Palapeli::MoveViewportInteractor::mouseMoveEvent(const Palapeli::MouseEvent
Palapeli::ZoomViewportInteractor::ZoomViewportInteractor(QGraphicsView* view)
: Palapeli::Interactor(Palapeli::WheelInteractor, view)
{
setMetadata(i18n("Zoom viewport"), QIcon());
setMetadata(i18nc("Description (used like a name) for a mouse interaction method", "Zoom viewport"), QIcon());
}
void Palapeli::ZoomViewportInteractor::wheelEvent(const Palapeli::WheelEvent& event)
......@@ -237,7 +257,7 @@ Palapeli::RubberBandInteractor::RubberBandInteractor(QGraphicsView* view)
: Palapeli::Interactor(Palapeli::MouseInteractor, view)
, m_item(new Palapeli::RubberBandItem)
{
setMetadata(i18n("Select multiple pieces at once"), QIcon());
setMetadata(i18nc("Description (used like a name) for a mouse interaction method", "Select multiple pieces at once"), QIcon());
if (scene())
scene()->addItem(m_item);
m_item->hide(); //NOTE: This is not necessary for the painting, but we use m_item->isVisible() to determine whether we are rubberbanding at the moment.
......
......@@ -23,12 +23,13 @@
#include <QGraphicsItem>
//TODO: interactor for selecting and deselecting pieces by clicking (like provided by QGV when Ctrl is held down)
namespace Palapeli
{
class Piece;
//This interactor is assigned to LeftButton;NoModifier by default.
//1. When you click on and drag a selected piece, all selected pieces are moved.
//2. When you click on and drag an unselected piece, all other pieces are deselected, the clicked piece is selected and moved.
class MovePieceInteractor : public Palapeli::Interactor
{
public:
......@@ -48,6 +49,21 @@ namespace Palapeli
QList<QPointF> m_basePositions;
};
//This interactor is assigned to LeftButton;ControlModifier by default.
//When you click on a piece, its selection state will be toggled.
class SelectPieceInteractor : public Palapeli::Interactor
{
public:
SelectPieceInteractor(QGraphicsView* view);
protected:
virtual bool acceptMousePosition(const QPoint& pos);
virtual void mousePressEvent(const Palapeli::MouseEvent& event);
private:
Palapeli::Piece* m_currentPiece;
};
//This interactor is assigned to RightButton;NoModifier by default.
//Dragging will drag the viewport (only translations, no rotation or zooming).
class MoveViewportInteractor : public Palapeli::Interactor
{
public:
......@@ -59,6 +75,8 @@ namespace Palapeli
QPoint m_lastPos;
};
//This interactor is assigned to wheel:Vertical;NoModifier by default.
//Turning the wheel will zoom the viewport.
class ZoomViewportInteractor : public Palapeli::Interactor
{
public:
......@@ -81,6 +99,8 @@ namespace Palapeli
QRectF m_rect;
};
//This interactor is assigned to LeftClick;NoModifier by default.
//When you click on a free area of the view and drag the mouse, a rectangular rubberband will appear. All pieces inside the rubberband will be selected, all other pieces are deselected.
class RubberBandInteractor : public Palapeli::Interactor
{
public:
......
......@@ -188,6 +188,12 @@ void Palapeli::Piece::setSelected(bool selected)
m_pieceItem->setSelected(selected);
}
Palapeli::Piece* Palapeli::Piece::fromSelectedItem(QGraphicsItem* item)
{
//We expect: item == piece->m_pieceItem && item->parentItem() == piece
return qgraphicsitem_cast<Palapeli::Piece*>(item->parentItem());
}
void Palapeli::Piece::beginMove()
{
static int zValue = 0;
......
......@@ -48,6 +48,9 @@ namespace Palapeli
bool isSelected() const;
void setSelected(bool selected);
///Returns the corresponding piece for an \a item found e.g. in QGraphicsScene::selectedItems(). This is different from a simple qgraphicsitem_cast because, internally, when you call setSelected(true) on a piece, a child item of this Piece is selected.
///\return 0 if the given \a item does not belong to a Piece
static Palapeli::Piece* fromSelectedItem(QGraphicsItem* item);
///This method lets the piece remember which atomic pieces it represents. (Atomic pieces are what the scene creates when the puzzle is loaded.)
void addRepresentedAtomicPieces(const QList<int>& representedAtomicPieces);
......
......@@ -328,10 +328,7 @@ void Palapeli::Scene::pieceMoved()
QList<Palapeli::Piece*> mergeCandidates;
foreach (QGraphicsItem* item, selectedItems())
{
//NOTE same as Palapeli::MovePieceInteractor::findPieceForItem
Palapeli::Piece* piece = qgraphicsitem_cast<Palapeli::Piece*>(item);
if (!piece)
piece = qgraphicsitem_cast<Palapeli::Piece*>(item->parentItem());
Palapeli::Piece* piece = Palapeli::Piece::fromSelectedItem(item);
if (piece)
mergeCandidates << piece;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment