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

0001 /* GCompris - InstructionArea.qml
0002  *
0003  * SPDX-FileCopyrightText: 2018 Aman Kumar Gupta <gupta2140@gmail.com>
0004  *
0005  * Authors:
0006  *   Aman Kumar Gupta <gupta2140@gmail.com>
0007  *   Timothée Giet <animtim@gcompris.net> (Layout and graphics rework)
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 import QtQuick 2.12
0012 import GCompris 1.0
0013 import "../../core"
0014 
0015 import "programmingMaze.js" as Activity
0016 
0017 GridView {
0018     id: instructionArea
0019     width: parent.width * 0.5
0020     height: parent.height * 0.17
0021     cellWidth: background.buttonWidth
0022     cellHeight: background.buttonHeight
0023 
0024     anchors.left: parent.left
0025     anchors.top: mazeModel.bottom
0026     anchors.topMargin: background.height * 0.4
0027 
0028     property string instructionText: qsTr("Choose the instructions")
0029 
0030     interactive: false
0031     model: instructionModel
0032 
0033     header: HeaderArea {
0034         width: instructionArea.width
0035         height: background.height / 11
0036         headerOpacity: 1
0037         headerText: instructionText
0038     }
0039 
0040     property string instructionToInsert
0041 
0042     signal spaceKeyPressed
0043     signal tabKeyPressed
0044 
0045     onSpaceKeyPressed: {
0046         if(instructionArea.currentIndex != -1)
0047             instructionArea.currentItem.selectCurrentInstruction()
0048     }
0049 
0050     onTabKeyPressed:  {
0051         instructionArea.currentIndex = -1
0052         background.areaWithKeyboardInput = mainFunctionCodeArea
0053     }
0054 
0055     highlight: Rectangle {
0056         width: buttonWidth - 3 * ApplicationInfo.ratio
0057         height: buttonHeight * 1.18 - 3 * ApplicationInfo.ratio
0058         color: "#00ffffff"
0059         border.width: 3.5 * ApplicationInfo.ratio //activity.keyboardNavigationVisible ? 3.5 * ApplicationInfo.ratio : 0
0060         border.color: "#e77935"
0061         z: 2
0062         radius: width / 18
0063     }
0064     highlightFollowsCurrentItem: true
0065     keyNavigationWraps: true
0066 
0067     delegate: Item {
0068         id: instructionItem
0069         width: background.buttonWidth
0070         height: background.buttonHeight * 1.18
0071 
0072         Rectangle {
0073             id: imageHolder
0074             width: parent.width - 3 * ApplicationInfo.ratio
0075             height: parent.height - 3 * ApplicationInfo.ratio
0076             border.width: 1.2 * ApplicationInfo.ratio
0077             border.color: "#2a2a2a"
0078             anchors.centerIn: parent
0079             radius: width / 18
0080             color: instructionArea.instructionToInsert == name ? "#f3bc9a" : "#ffffff"
0081 
0082             Image {
0083                 id: icon
0084                 source: Activity.url + name + ".svg"
0085                 width: Math.round(parent.width / 1.2)
0086                 height: Math.round(parent.height / 1.2)
0087                 sourceSize.width: height
0088                 sourceSize.height: height
0089                 anchors.centerIn: parent
0090                 fillMode: Image.PreserveAspectFit
0091                 mipmap: true
0092             }
0093         }
0094 
0095         MouseArea {
0096             id: mouseArea
0097             anchors.fill: parent
0098             enabled: items.isRunCodeEnabled && ((items.numberOfInstructionsAdded < items.maxNumberOfInstructionsAllowed) || procedureCodeArea.isEditingInstruction || mainFunctionCodeArea.isEditingInstruction)
0099 
0100             onPressed: instructionItem.checkModelAndInsert()
0101         }
0102 
0103         function selectCurrentInstruction() {
0104             if(!mainFunctionCodeArea.isEditingInstruction && !procedureCodeArea.isEditingInstruction) {
0105                 instructionArea.instructionToInsert = name
0106                 playClickedAnimation()
0107             }
0108             else {
0109                 if(mainFunctionCodeArea.isEditingInstruction)
0110                     insertIntoModel(mainFunctionModel, mainFunctionCodeArea)
0111                 if(procedureCodeArea.isEditingInstruction && (name !== Activity.CALL_PROCEDURE) && (name !== Activity.EXECUTE_LOOPS))
0112                     insertIntoModel(procedureModel, procedureCodeArea)
0113             }
0114         }
0115 
0116         function checkModelAndInsert() {
0117             if(items.constraintInstruction.opacity)
0118                 items.constraintInstruction.hide()
0119 
0120             if(!background.insertIntoMain && (name !== Activity.CALL_PROCEDURE) && (name !== Activity.EXECUTE_LOOPS))
0121                 insertIntoModel(procedureModel, procedureCodeArea)
0122             else if(background.insertIntoMain)
0123                 insertIntoModel(mainFunctionModel, mainFunctionCodeArea)
0124         }
0125 
0126         /**
0127          * If we are adding an instruction, append it to the model if number of instructions added is less than the maximum number of instructions allowed.
0128          * If editing, replace it with the selected instruction in the code area.
0129          */
0130         function insertIntoModel(model, area) {
0131             if(!area.isEditingInstruction) {
0132                 if(items.numberOfInstructionsAdded >= items.maxNumberOfInstructionsAllowed)
0133                     constraintInstruction.changeConstraintInstructionOpacity()
0134                 else {
0135                     playClickedAnimation()
0136                     model.append({ "name": name })
0137                     items.numberOfInstructionsAdded++
0138                 }
0139             }
0140             else {
0141                 playClickedAnimation()
0142                 model.set(area.initialEditItemIndex, {"name": name}, 1)
0143                 area.resetEditingValues()
0144             }
0145         }
0146 
0147         /**
0148          * If two successive clicks on the same icon are made very fast, stop the ongoing animation and set the scale back to 1.
0149          * Then start the animation for next click.
0150          * This gives proper feedback of multiple clicks.
0151          */
0152         function playClickedAnimation() {
0153             clickedAnimation.stop()
0154             icon.scale = 1
0155             clickedAnimation.start()
0156         }
0157 
0158         SequentialAnimation {
0159             id: clickedAnimation
0160             PropertyAnimation {
0161                 target: imageHolder
0162                 property: "scale"
0163                 to: 0.8
0164                 duration: 150
0165             }
0166 
0167             PropertyAnimation {
0168                 target: imageHolder
0169                 property: "scale"
0170                 to: 1
0171                 duration: 150
0172             }
0173         }
0174     }
0175 }