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

0001 /* GCompris - MasseArea.qml
0002  *
0003  * SPDX-FileCopyrightText: 2014 Bruno Coudoin <bruno.coudoin@gcompris.net>
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
0007  *
0008  *   SPDX-License-Identifier: GPL-3.0-or-later
0009  */
0010 import QtQuick 2.12
0011 import QtGraphicalEffects 1.0
0012 
0013 import "../../core"
0014 import "scalesboard.js" as Activity
0015 
0016 Rectangle {
0017     id: masseArea
0018     height: itemHeight
0019     color: dropArea.containsDrag ? "#33333333" : "#00000000"
0020     border.width: 2
0021     border.color: dropArea.containsDrag ? "#33666666" : "#00000000"
0022 
0023     property bool dropEnabled: true
0024     property bool dropEnabledForThisLevel: true
0025     property int nbColumns
0026     property int itemWidth: (width - masseFlow.spacing * nbColumns) / nbColumns
0027     property int itemHeight: itemWidth * 1.2
0028 
0029     property Item masseAreaCenter
0030     property Item masseAreaLeft
0031     property Item masseAreaRight
0032 
0033     property alias masseModel: masseModel
0034     property alias dropArea: dropArea
0035 
0036     property int weight: 0
0037 
0038     property GCSfx audioEffects
0039 
0040     function init() {
0041         weight = 0
0042         masseModel.clear()
0043     }
0044 
0045     function removeWeight(value) {
0046         weight -= value
0047     }
0048 
0049     function removeMasse(masseArea, index, weight) {
0050         masseArea.removeWeight(weight)
0051         masseArea.masseModel.remove(index)
0052     }
0053 
0054     /* weight is the absolute weight
0055      * text is the text being displayed on the masseAreaCenter
0056      */
0057     function addMasse(img, weight, text, index, dragEnabled) {
0058         masseModel.append( {
0059                               img: img,
0060                               weight: weight,
0061                               text: text,
0062                               masseIndex: index,
0063                               opacity: 1.0,
0064                               dragEnabled: dragEnabled
0065                           } )
0066         masseArea.weight += weight
0067     }
0068 
0069     function setAllZonesDropEnabled(enabled) {
0070         masseAreaCenter.dropEnabled = enabled
0071         masseAreaLeft.dropEnabled = enabled
0072         masseAreaRight.dropEnabled = enabled
0073     }
0074 
0075     function showMasseInMasseArea(index) {
0076         masseAreaCenter.masseModel.get(index).opacity = 1.0
0077     }
0078 
0079     function hideMasseInMasseArea(index) {
0080         masseAreaCenter.masseModel.get(index).opacity = 0.0
0081     }
0082 
0083     ListModel {
0084         id: masseModel
0085 
0086         function contains(masseIndex) {
0087             for(var i = 0; i < masseModel.count; i++) {
0088                 if(masseModel.get(i).masseIndex == masseIndex) {
0089                     return masseModel.get(i).opacity == 1
0090                 }
0091             }
0092             return false;
0093         }
0094     }
0095 
0096     DropArea {
0097         id: dropArea
0098         anchors {
0099             left: parent.left
0100             right: parent.right
0101             verticalCenter: parent.verticalCenter
0102         }
0103         height: parent.height * 2
0104         enabled: dropEnabledForThisLevel && dropEnabled
0105     }
0106 
0107     Flow {
0108         id: masseFlow
0109         anchors.topMargin: 4
0110         anchors.bottomMargin: 4
0111         anchors.fill: parent
0112         spacing: 10
0113         flow: Flow.TopToBottom
0114 
0115         add: Transition {
0116             NumberAnimation {
0117                 properties: "x"
0118                 from: parent.width * 0.05
0119                 easing.type: Easing.InOutQuad
0120             }
0121         }
0122 
0123         move: Transition {
0124             NumberAnimation {
0125                 properties: "x,y"
0126                 easing.type: Easing.InOutQuad
0127             }
0128         }
0129 
0130         Repeater {
0131             id: answer
0132             model: masseModel
0133             Image {
0134                 source: Activity.url + img
0135                 sourceSize.height: masseArea.itemHeight
0136                 height: masseArea.itemHeight
0137                 opacity: model.opacity
0138 
0139                 property string img: model.img
0140                 property int masseIndex: model.masseIndex
0141                 property int modelIndex: index
0142                 property int weight: model.weight
0143                 property string text: model.text
0144                 property int masseOriginX
0145                 property int masseOriginY
0146                 property int originX
0147                 property int originY
0148                 property Item currentMasseArea: masseArea
0149 
0150                 Drag.active: dragArea.drag.active
0151                 Drag.hotSpot.x: width / 2
0152                 Drag.hotSpot.y: height / 2
0153 
0154                 function initDrag() {
0155                     originX = x
0156                     originY = y
0157                     if(currentMasseArea == masseArea) {
0158                         masseOriginX = x
0159                         masseOriginY = y
0160                     }
0161                     z = 111
0162                 }
0163 
0164                 function replace() {
0165                     x = originX
0166                     y = originY
0167                 }
0168 
0169                 function replaceInMasse() {
0170                     x = masseOriginX
0171                     y = masseOriginY
0172                 }
0173 
0174                 onOpacityChanged: opacity == 1.0 ? currentMasseArea = masseAreaCenter : null
0175 
0176                 MouseArea {
0177                     id: dragArea
0178                     anchors.fill: parent
0179                     drag.target: parent
0180                     enabled: model.dragEnabled && !items.buttonsBlocked
0181 
0182                     onPressed: {
0183                         message.text = ""
0184                         if(masseModel.contains(parent.masseIndex)) {
0185                             parent.initDrag()
0186                         }
0187                         else {
0188                             setAllZonesDropEnabled(false)
0189                         }
0190                     }
0191 
0192                     function dropOnPlate(masseArea) {
0193                         parent.Drag.cancel()
0194                         if(parent.currentMasseArea == masseAreaCenter) {
0195                             masseArea.hideMasseInMasseArea(parent.masseIndex)
0196                             parent.replaceInMasse()
0197                         }
0198                         masseArea.addMasse(parent.img,
0199                                            parent.weight,
0200                                            parent.text,
0201                                            parent.masseIndex,
0202                                            /* dragEnabled */ true)
0203                         if(parent.currentMasseArea != masseAreaCenter) {
0204                             removeMasse(parent.currentMasseArea,
0205                                         parent.modelIndex, parent.weight)
0206                         }
0207 
0208                         parent.currentMasseArea = masseArea
0209                     }
0210 
0211                     onReleased: {
0212                         setAllZonesDropEnabled(true)
0213                         if(masseArea.audioEffects)
0214                             masseArea.audioEffects.play(Activity.url + 'metal_hit.wav')
0215                         if(masseAreaLeft.dropArea.containsDrag &&
0216                            parent.currentMasseArea != masseAreaLeft) {
0217                             dropOnPlate(masseAreaLeft)
0218                         } else if (masseAreaRight.dropArea.containsDrag &&
0219                                    parent.currentMasseArea != masseAreaRight) {
0220                             dropOnPlate(masseAreaRight)
0221                         } else if (masseAreaCenter.dropArea.containsDrag &&
0222                                    parent.dropArea != masseAreaCenter) {
0223                             parent.Drag.cancel()
0224                             masseAreaCenter.showMasseInMasseArea(parent.masseIndex)
0225                             parent.replaceInMasse()
0226                             if(parent.currentMasseArea != masseAreaCenter) {
0227                                 removeMasse(parent.currentMasseArea,
0228                                             parent.modelIndex, parent.weight)
0229                             }
0230                         } else {
0231                             parent.Drag.cancel()
0232                             parent.replace()
0233                         }
0234 
0235                     }
0236                 }
0237 
0238                 GCText {
0239                     id: text
0240                     anchors.fill: parent
0241                     text: model.text.replace(" ", "\n")
0242                     color: "white"
0243                     fontSizeMode: Text.Fit
0244                     minimumPointSize: 10
0245                     fontSize: largeSize
0246                     font.bold : true
0247                     style: Text.Outline
0248                     styleColor: "black"
0249                     horizontalAlignment: Text.AlignHCenter
0250                     verticalAlignment: Text.AlignVCenter
0251                 }
0252 
0253                 DropShadow {
0254                     anchors.fill: text
0255                     cached: false
0256                     horizontalOffset: 3
0257                     verticalOffset: 3
0258                     radius: 8.0
0259                     samples: 16
0260                     color: "#80000000"
0261                     source: text
0262                 }
0263             }
0264 
0265         }
0266     }
0267 
0268     Behavior on y {
0269         NumberAnimation {
0270             duration: 500
0271             easing.type: Easing.InOutQuad
0272         }
0273     }
0274 
0275 }