Warning, /education/gcompris/src/activities/crane/Crane.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - Crane.qml
0002  *
0003  * SPDX-FileCopyrightText: 2016 Stefan Toncu <stefan.toncu29@gmail.com>
0004  * SPDX-FileCopyrightText: 2020 Timothée Giet <animtim@gmail.com>
0005  *
0006  * Authors:
0007  *   <Marc BRUN> (GTK+ version)
0008  *   Stefan Toncu <stefan.toncu29@gmail.com> (Qt Quick port)
0009  *   Timothée Giet <animtim@gmail.com> (layout refactoring)
0010  *
0011  *   SPDX-License-Identifier: GPL-3.0-or-later
0012  */
0013 
0014 import QtQuick 2.12
0015 import QtGraphicalEffects 1.0
0016 import GCompris 1.0
0017 
0018 import "../../core"
0019 import "crane.js" as Activity
0020 
0021 ActivityBase {
0022     id: activity
0023 
0024     // Overload this in your activity to change it
0025     // Put you default-<locale>.json files in it
0026     property string dataSetUrl: "qrc:/gcompris/src/activities/crane/resource/"
0027 
0028     onStart: focus = true
0029     onStop: {}
0030 
0031     pageComponent: Image {
0032         id: background
0033         source: activity.dataSetUrl+"background.svg"
0034         fillMode: Image.PreserveAspectCrop
0035         anchors.fill: parent
0036         sourceSize.width: width
0037         sourceSize.height: height
0038 
0039         signal start
0040         signal stop
0041 
0042         Component.onCompleted: {
0043             activity.start.connect(start)
0044             dialogActivityConfig.initialize()
0045             activity.stop.connect(stop)
0046         }
0047 
0048         // Add here the QML items you need to access in javascript
0049         QtObject {
0050             id: items
0051             property Item main: activity.main
0052             property alias background: background
0053             property GCSfx audioEffects: activity.audioEffects
0054             property int currentLevel: activity.currentLevel
0055             property alias bonus: bonus
0056             property alias board: board
0057             property alias grid: answerGrid
0058             property alias answerRepeater: answerRepeater
0059             property alias modelRepeater: modelRepeater
0060             property alias gridRepeater: gridRepeater
0061             property alias showGrid1: showGrid1
0062             property alias score: score
0063             property alias selector: selector
0064             property int selected: -1
0065             property int columns
0066             property int rows
0067             property bool ok: true
0068             property int sensivity: 80
0069             property bool pieceIsMoving: false
0070             readonly property var levels: activity.datasetLoader.data
0071             property double gridBaseWidth: items.board.width / items.columns
0072             property double gridBaseHeight: items.board.height / items.rows
0073             property bool buttonsBlocked: false
0074         }
0075 
0076         onStart: { Activity.start(items) }
0077         onStop: { Activity.stop() }
0078 
0079         property bool portrait: height >= width ? true : false
0080         property bool inLine: true
0081 
0082         Keys.onPressed: {
0083             if (items.buttonsBlocked){
0084                 return
0085             }
0086             else if (event.key === Qt.Key_Left){
0087                 Activity.move("left")
0088                 left.opacity = 0.6
0089             }
0090             else if (event.key === Qt.Key_Right){
0091                 Activity.move("right")
0092                 right.opacity = 0.6
0093             }
0094             else if (event.key === Qt.Key_Up){
0095                 Activity.move("up")
0096                 up.opacity = 0.6
0097             }
0098             else if (event.key === Qt.Key_Down){
0099                 Activity.move("down")
0100                 down.opacity = 0.6
0101             }
0102             else if (event.key === Qt.Key_Space ||
0103                      event.key === Qt.Key_Tab ||
0104                      event.key === Qt.Key_Enter ||
0105                      event.key === Qt.Key_Return)
0106                 Activity.move("next")
0107         }
0108 
0109         Keys.onReleased: {
0110             up.opacity = 1
0111             down.opacity = 1
0112             left.opacity = 1
0113             right.opacity = 1
0114         }
0115 
0116         Item {
0117             id: layoutArea
0118             anchors.top: background.top
0119             anchors.bottom: bar.top
0120             anchors.left: background.left
0121             anchors.right: background.right
0122             anchors.bottomMargin: bar.height * 0.2
0123         }
0124 
0125         //implementation of Swipe effect
0126         MouseArea {
0127             anchors.fill: layoutArea
0128             property int startX;
0129             property int startY;
0130             enabled: !items.buttonsBlocked
0131 
0132             onPressed: {
0133                 startX = mouse.x;
0134                 startY = mouse.y;
0135             }
0136             onReleased: Activity.gesture(mouse.x - startX, mouse.y - startY)
0137         }
0138 
0139         Rectangle {
0140             id: boardBg
0141             color: "#77c0d9"
0142             radius: width * 0.03
0143             border.color: "#77c0d9"
0144             border.width: width * 0.02
0145             z: 1
0146             clip: true
0147 
0148             anchors {
0149                 top: crane_top.bottom
0150                 bottom: crane_body.top
0151                 right: crane_vertical.left
0152                 margins: 5 * ApplicationInfo.ratio
0153             }
0154 
0155             width: background.portrait ? (layoutArea.width - crane_vertical.width) * 0.8 : ((layoutArea.width - anchors.margins * 2 - crane_vertical.width) * 0.5 ) * 0.9
0156         }
0157 
0158         Rectangle {
0159             id: board
0160             z: 1
0161             color: "#b9e2f0"
0162             anchors.centerIn: boardBg
0163             width: boardBg.width - boardBg.border.width * 2
0164             height: boardBg.height - boardBg.border.width * 2
0165         }
0166 
0167         Grid {
0168             id: showGrid1
0169             columns: items.columns
0170             rows: items.rows
0171             z: 1
0172             anchors.centerIn: board
0173             layer.enabled: ApplicationInfo.useOpenGL
0174             layer.effect: OpacityMask {
0175                 maskSource: board
0176             }
0177             Repeater {
0178                 id: gridRepeater
0179 
0180                 Rectangle {
0181                     width: items.gridBaseWidth
0182                     height: items.gridBaseHeight
0183                     color: "transparent"
0184                     border.width: 2
0185                     border.color: "#77c0d9"
0186                 }
0187             }
0188         }
0189 
0190 
0191         Grid {
0192             id: answerGrid
0193             columns: items.columns
0194             rows: items.rows
0195             z: 4
0196             anchors.centerIn: board
0197 
0198             Repeater {
0199                 id: answerRepeater
0200 
0201                 Image {
0202                     id: figure
0203                     sourceSize.height: height
0204                     sourceSize.width: width
0205                     width: items.gridBaseWidth
0206                     height: items.gridBaseHeight
0207                     fillMode: Image.PreserveAspectFit
0208 
0209                     property int initialIndex: -1
0210 
0211                     property alias anim: anim
0212                     property int distance
0213                     property int indexChange
0214                     property int startPoint
0215                     property string animationProperty
0216                     property int _index: index // make current index accessible from outside
0217 
0218                     SequentialAnimation {
0219                         id: anim
0220                         PropertyAction { target: items; property: "ok"; value: "false"}
0221                         NumberAnimation { target: figure; property: figure.animationProperty; from: figure.startPoint; to: figure.startPoint + distance; duration: 200 }
0222                         PropertyAction { target: figure; property: "opacity"; value: 0 }
0223                         NumberAnimation { target: figure; property: figure.animationProperty; from: figure.startPoint + distance; to: figure.startPoint; duration: 0; }
0224                         PropertyAction { target: figure; property: "opacity"; value: 1 }
0225                         PropertyAction { target: items.answerRepeater.itemAt(items.selected + indexChange); property: "source"; value: figure.source }
0226                         PropertyAction { target: items.answerRepeater.itemAt(items.selected + indexChange); property: "initialIndex"; value: figure.initialIndex }
0227                         PropertyAction { target: figure; property: "initialIndex"; value: -1 }
0228                         PropertyAction { target: figure; property: "source"; value: "" }
0229                         PropertyAction { target: items; property: "ok"; value: "true"}
0230                         PropertyAction { target: items; property: "pieceIsMoving"; value: "false"}
0231                         ScriptAction { script: Activity.checkAnswer() }
0232                     }
0233 
0234                     MouseArea {
0235                         anchors.fill: parent
0236                         enabled: !items.buttonsBlocked
0237 
0238                         // Swipe effect
0239                         property int startX;
0240                         property int startY;
0241 
0242                         onPressed: {
0243                             startX = mouse.x;
0244                             startY = mouse.y;
0245                         }
0246 
0247                         onReleased:
0248                             Activity.gesture(mouse.x - startX, mouse.y - startY)
0249 
0250                         // Select a figure with mouse/touch
0251                         onClicked: {
0252                             if (source != "" && !items.pieceIsMoving)
0253                                 items.selected = index
0254                         }
0255                     }
0256                 }
0257             }
0258         }
0259 
0260         Image {
0261             id: selector
0262             source: activity.dataSetUrl+"selected.svg"
0263             sourceSize.width: width
0264             sourceSize.height: height
0265             width: items.gridBaseWidth
0266             height: items.gridBaseHeight
0267             opacity: 1
0268             state: "uninitialized"
0269 
0270             x: 0
0271             y: 0
0272             z: 100
0273 
0274             Behavior on x { NumberAnimation { duration: 200 } }
0275             Behavior on y { NumberAnimation { duration: 200 } }
0276 
0277             states: [
0278                 State {
0279                     name: "uninitialized"
0280                     PropertyChanges {
0281                         target: selector
0282                         x: 0
0283                         y: 0
0284                     }
0285                     PropertyChanges {
0286                         target: cable
0287                         height: 0
0288                         x: 0
0289                     }
0290                 },
0291                 State {
0292                     name: "initialized"
0293                     PropertyChanges {
0294                         target: selector
0295                         x: answerRepeater.itemAt(items.selected) ? answerRepeater.itemAt(items.selected).x + board.x : 0
0296                         y: answerRepeater.itemAt(items.selected) ? answerRepeater.itemAt(items.selected).y + board.y : 0
0297                     }
0298                     PropertyChanges {
0299                         target: cable
0300                         height: answerRepeater.itemAt(items.selected) ? answerRepeater.itemAt(items.selected).y + board.y - crane_top.y : 0
0301                         x: answerRepeater.itemAt(items.selected) ? answerRepeater.itemAt(items.selected).x + board.x + items.gridBaseWidth / 2 : 0
0302                     }
0303                 }
0304             ]
0305 
0306         }
0307 
0308         Rectangle {
0309             id: modelBoardBg
0310             color: "#e294b7"
0311             radius: width * 0.03
0312             border.color: "#e294b7"
0313             border.width: width * 0.02
0314             z: 1
0315 
0316             anchors {
0317                 left: background.portrait ? boardBg.left : crane_vertical.right
0318                 top: background.portrait ? crane_body.bottom : background.inLine ? boardBg.top : parent.top
0319                 topMargin: background.portrait ? boardBg.anchors.margins : background.inLine ? 0 : crane_top.height * 1.5
0320                 leftMargin: background.portrait ? 0 : boardBg.anchors.margins * 1.2
0321                 margins: boardBg.anchors.margins
0322             }
0323 
0324             width: boardBg.width
0325             height: boardBg.height
0326         }
0327 
0328         Rectangle {
0329             id: modelBoard
0330             z: 1
0331             color: "#f0b9d2"
0332             anchors.centerIn: modelBoardBg
0333             width: board.width
0334             height: board.height
0335         }
0336 
0337         Grid {
0338             id: modelGrid
0339             columns: items.columns
0340             rows: items.rows
0341             anchors.centerIn: modelBoard
0342             z: 4
0343 
0344             Repeater {
0345                 id: modelRepeater
0346 
0347                 Image {
0348                     id: modelFigure
0349                     sourceSize.height: height
0350                     sourceSize.width: width
0351                     width: items.gridBaseWidth
0352                     height: items.gridBaseHeight
0353                     fillMode: Image.PreserveAspectFit
0354                 }
0355             }
0356         }
0357 
0358         Grid {
0359             id: showGrid2
0360             columns: items.columns
0361             rows: items.rows
0362             z: 1
0363             opacity: showGrid1.opacity
0364             anchors.centerIn: modelBoard
0365             layer.enabled: ApplicationInfo.useOpenGL
0366             layer.effect: OpacityMask {
0367                 maskSource: modelBoard
0368             }
0369             Repeater {
0370                 id: gridRepeater2
0371                 model: gridRepeater.model
0372 
0373                 Rectangle {
0374                     width: items.gridBaseWidth
0375                     height: items.gridBaseHeight
0376                     color: "transparent"
0377                     border.width: 2
0378                     border.color: showGrid1.opacity == 1 ? "#e294b7" : "transparent"
0379                 }
0380             }
0381         }
0382 
0383 
0384         Image {
0385             id: crane_top
0386             source: activity.dataSetUrl+"crane_up.svg"
0387             sourceSize.width: width
0388             width: background.portrait ? layoutArea.width * 0.8: layoutArea.width * 0.5
0389             fillMode: Image.PreserveAspectFit
0390             z: 4
0391             anchors {
0392                 top: layoutArea.top
0393                 right: crane_vertical.right
0394                 rightMargin: 0
0395                 margins: boardBg.anchors.margins
0396             }
0397         }
0398 
0399         Image {
0400             id: crane_vertical
0401             source: activity.dataSetUrl+"crane_vertical.svg"
0402             sourceSize.height: height
0403             fillMode: Image.PreserveAspectFit
0404             anchors {
0405                 top: crane_top.top
0406                 bottom: crane_body.verticalCenter
0407                 right: background.portrait ? layoutArea.right : layoutArea.horizontalCenter
0408                 rightMargin: background.portrait ? width / 2 : - width / 2
0409                 topMargin: boardBg.anchors.margins
0410             }
0411         }
0412 
0413         Image {
0414             id: crane_body
0415             source: activity.dataSetUrl+"crane_only.svg"
0416             z: 2
0417             height: bar.height
0418             sourceSize.height: height
0419             fillMode: Image.PreserveAspectFit
0420             mirror: background.portrait ? true : false
0421             anchors.verticalCenterOffset: crane_top.height * 0.5
0422         }
0423 
0424         Image {
0425             id: crane_command
0426             source: activity.dataSetUrl+"command.svg"
0427             sourceSize.height: height
0428             anchors.margins: 5 * ApplicationInfo.ratio
0429             fillMode: Image.PreserveAspectFit
0430             Controls {
0431                 id: up
0432                 source: activity.dataSetUrl+"arrow_up.svg"
0433                 anchors {
0434                     right: parent.horizontalCenter
0435                     rightMargin: width * 1.15
0436                 }
0437                 command: "up"
0438             }
0439 
0440             Controls {
0441                 id: down
0442                 source: activity.dataSetUrl+"arrow_down.svg"
0443                 anchors {
0444                     right: parent.horizontalCenter
0445                     rightMargin: width * 0.1
0446                 }
0447                 command: "down"
0448             }
0449 
0450             Controls {
0451                 id: left
0452                 source: activity.dataSetUrl+"arrow_left.svg"
0453                 anchors {
0454                     left: parent.horizontalCenter
0455                     leftMargin: width * 0.1
0456                 }
0457                 command: "left"
0458             }
0459 
0460             Controls {
0461                 id: right
0462                 source: activity.dataSetUrl+"arrow_right.svg"
0463                 anchors {
0464                     left: parent.horizontalCenter
0465                     leftMargin: width * 1.15
0466                 }
0467                 command: "right"
0468             }
0469         }
0470 
0471         Rectangle {
0472             id: cable
0473             color: "#373737"
0474             width: 5
0475             height: 0
0476             x: 0
0477             z: 3
0478             anchors.top: crane_top.top
0479             anchors.topMargin: 10
0480 
0481             Behavior on x { NumberAnimation { duration: 200 } }
0482             Behavior on height { NumberAnimation { duration: 200 } }
0483         }
0484 
0485         states: [
0486             State {
0487                 name: "horizontal"
0488                 when: !background.portrait
0489                 PropertyChanges{
0490                     target: crane_command
0491                     width: boardBg.width
0492                 }
0493                 AnchorChanges{
0494                     target: crane_body
0495                     anchors.left: crane_vertical.left
0496                     anchors.right: undefined
0497                     anchors.bottom: layoutArea.bottom
0498                     anchors.verticalCenter: undefined
0499                 }
0500                 AnchorChanges{
0501                     target: score
0502                     anchors.right: modelBoardBg.right
0503                     anchors.bottom: undefined
0504                     anchors.verticalCenter: crane_body.verticalCenter
0505                     anchors.left: undefined
0506                 }
0507                 AnchorChanges{
0508                     target:crane_command
0509                     anchors.top: boardBg.bottom
0510                     anchors.bottom: crane_body.bottom
0511                     anchors.right: undefined
0512                     anchors.left: undefined
0513                     anchors.horizontalCenter: boardBg.horizontalCenter
0514                 }
0515             },
0516             State {
0517                 name: "vertical"
0518                 when: background.portrait
0519                 PropertyChanges{
0520                     target: crane_command
0521                     width: undefined
0522                 }
0523                 AnchorChanges{
0524                     target: crane_body
0525                     anchors.left: undefined
0526                     anchors.right: crane_vertical.right
0527                     anchors.bottom: undefined
0528                     anchors.verticalCenter: layoutArea.verticalCenter
0529                 }
0530                 AnchorChanges{
0531                     target: score
0532                     anchors.right: undefined
0533                     anchors.bottom: undefined
0534                     anchors.verticalCenter: crane_body.verticalCenter
0535                     anchors.left: layoutArea.left
0536                 }
0537                 AnchorChanges{
0538                     target:crane_command
0539                     anchors.top: boardBg.bottom
0540                     anchors.bottom: modelBoardBg.top
0541                     anchors.right: crane_body.left
0542                     anchors.left: score.right
0543                     anchors.horizontalCenter: undefined
0544                 }
0545             }
0546         ]
0547 
0548 
0549         DialogHelp {
0550             id: dialogHelp
0551             onClose: home()
0552         }
0553 
0554         DialogChooseLevel {
0555             id: dialogActivityConfig
0556             currentActivity: activity.activityInfo
0557             onClose: {
0558                 home()
0559             }
0560 
0561             onSaveData: {
0562                 levelFolder = dialogActivityConfig.chosenLevels
0563                 currentActivity.currentLevels = dialogActivityConfig.chosenLevels
0564                 ApplicationSettings.setCurrentLevels(currentActivity.name, dialogActivityConfig.chosenLevels)
0565             }
0566 
0567             onStartActivity: {
0568                 background.stop()
0569                 background.start()
0570             }
0571         }
0572 
0573         Bar {
0574             id: bar
0575             level: items.currentLevel + 1
0576             content: BarEnumContent { value: help | home | level | activityConfig}
0577             onHelpClicked: {
0578                 displayDialog(dialogHelp)
0579             }
0580             onPreviousLevelClicked: Activity.previousLevel()
0581             onNextLevelClicked: Activity.nextLevel()
0582             onHomeClicked: activity.home()
0583             onActivityConfigClicked: {
0584                 displayDialog(dialogActivityConfig)
0585             }
0586         }
0587 
0588         Bonus {
0589             id: bonus
0590             Component.onCompleted: win.connect(Activity.nextLevel)
0591         }
0592 
0593         Score {
0594             id: score
0595             visible: true
0596             anchors.right: modelBoardBg.right
0597             anchors.margins: 5 * ApplicationInfo.ratio
0598             onStop: { Activity.nextSubLevel() }
0599         }
0600     }
0601 
0602 }