130 lines
4.4 KiB
QML
130 lines
4.4 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
|
|
ApplicationWindow {
|
|
width: 750
|
|
height: 650
|
|
visible: true
|
|
title: qsTr("Solitare")
|
|
color: "green"
|
|
|
|
ScoreBar {
|
|
id: scoreBar
|
|
height: 50
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
}
|
|
|
|
// Show the foundation piles, throwaway pile & the draw stack on the first row
|
|
Item {
|
|
id: firstRow
|
|
height: 120
|
|
anchors.top: scoreBar.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
|
|
Item {
|
|
anchors.fill: parent
|
|
anchors.margins: 10
|
|
|
|
// Left row (with the foundation piles)
|
|
Row {
|
|
spacing: 15
|
|
anchors.left: parent.left
|
|
|
|
Repeater {
|
|
model: 4 // Each of the 4 suits
|
|
CardModel {
|
|
required property int index; // passed from repeater
|
|
card: GameState.foundation[index].length > 0 ? GameState.foundation[index][0] : null
|
|
isFaceDown: false
|
|
}
|
|
}
|
|
}
|
|
|
|
// Spacer to push the second row to the right
|
|
Item {
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
// Right row (with throwaway and draw piles)
|
|
Row {
|
|
spacing: 20
|
|
anchors.right: parent.right
|
|
|
|
// Throwaway pile (last 3 cards visible with overlap)
|
|
Row {
|
|
// This allows makes the cards overlap
|
|
spacing: -60
|
|
|
|
Repeater {
|
|
model: Math.min(GameState.throwawayPile.length, 3)
|
|
delegate: CardModel {
|
|
required property int index // passed from repeater
|
|
property int reversedIndex: Math.min(GameState.throwawayPile.length, 3) - 1 - index;
|
|
card: GameState.throwawayPile[GameState.throwawayPile.length - 1 - reversedIndex]
|
|
isFaceDown: false
|
|
onClicked: {
|
|
// Only auto-move the last card in the throwaway pile
|
|
// cards below it are shown, but shouldn't have a click effect
|
|
if (reversedIndex == 0) {
|
|
GameState.autoMoveThrownCard()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw pile (only the top card is shown)
|
|
CardModel {
|
|
card: GameState.drawPile.length > 0 ? GameState.drawPile[GameState.drawPile.length - 1] : null
|
|
isFaceDown: GameState.drawPile.length > 0 ? true : false
|
|
onClicked: {
|
|
GameState.drawNextCard()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Second row, with the individual columns
|
|
Row {
|
|
spacing: 10
|
|
|
|
anchors.top: firstRow.bottom
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.topMargin: 50
|
|
|
|
Repeater {
|
|
model: GameState.columns.length
|
|
|
|
delegate: Column {
|
|
required property int index // passed from repeater
|
|
spacing: -80 // Overlap
|
|
|
|
Repeater {
|
|
model: GameState.columns[parent.index].length > 0
|
|
? GameState.columns[parent.index].length
|
|
: 1 // Render an empty slot for an empty column
|
|
delegate: CardModel {
|
|
required property int index
|
|
property ColumnSlot col: GameState.columns[parent.index].length > 0
|
|
? GameState.columns[parent.index][index]
|
|
: null // empty column (single empty slot)
|
|
|
|
card: col ? col.card : null
|
|
isFaceDown: col ? !col.revealed : false
|
|
onClicked: {
|
|
if (col && col.revealed) {
|
|
GameState.autoMoveColumnCard(parent.index, index)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|