Warning, /education/gcompris/src/activities/graph-coloring/GraphColoring.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - graph-coloring.qml 0002 * 0003 * SPDX-FileCopyrightText: 2015 Akshat Tandon <akshat.tandon@research.iiit.ac.in> 0004 * 0005 * Authors: 0006 * 0007 * Akshat Tandon <akshat.tandon@research.iiit.ac.in> (Qt Quick version) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 import QtQuick 2.12 0012 0013 import "../../core" 0014 import "graph-coloring.js" as Activity 0015 import GCompris 1.0 0016 0017 ActivityBase { 0018 id: activity 0019 0020 onStart: focus = true 0021 onStop: {} 0022 0023 // When opening a dialog, it steals the focus and re set it to the activity. 0024 // We need to set it back to the eventHandler item in order to have key events. 0025 onFocusChanged: { 0026 if(focus) { 0027 Activity.focusEventInput() 0028 } 0029 } 0030 0031 pageComponent: Image { 0032 id: background 0033 anchors.fill: parent 0034 source: "qrc:/gcompris/src/activities/tic_tac_toe/resource/background.svg" 0035 sourceSize.width: width 0036 sourceSize.height: height 0037 fillMode: Image.PreserveAspectCrop 0038 0039 signal start 0040 signal stop 0041 0042 Component.onCompleted: { 0043 dialogActivityConfig.initialize() 0044 activity.start.connect(start) 0045 activity.stop.connect(stop) 0046 } 0047 0048 MouseArea { 0049 anchors.fill: parent 0050 onClicked: showChooser(false); 0051 } 0052 0053 // Add here the QML items you need to access in javascript 0054 QtObject { 0055 id: items 0056 property Item main: activity.main 0057 property alias background: background 0058 property int currentLevel: activity.currentLevel 0059 property alias bonus: bonus 0060 property alias colorsRepeater: colorsRepeater 0061 property alias nodesRepeater: nodesRepeater 0062 property alias edgesRepeater: edgesRepeater 0063 property alias chooserGrid: chooserGrid 0064 property alias nodeHighlight: nodeHighlight 0065 property string mode: "color" 0066 property var currentKeyZone: graphRect 0067 property bool keyNavigationMode: false 0068 property alias eventHandler: eventHandler 0069 } 0070 0071 onStart: { 0072 Activity.start(items); 0073 eventHandler.forceActiveFocus(); 0074 } 0075 onStop: { Activity.stop() } 0076 0077 Item { 0078 id: eventHandler 0079 focus: true 0080 Keys.enabled: !bonus.isPlaying && !dialogActivityConfig.visible 0081 Keys.onPressed: { 0082 items.keyNavigationMode = true; 0083 items.currentKeyZone.handleKeys(event); 0084 } 0085 } 0086 0087 Column { 0088 id: colorsColumn 0089 0090 anchors.left: parent.left 0091 anchors.leftMargin: 5 * ApplicationInfo.ratio 0092 anchors.top: parent.top 0093 anchors.topMargin: 5 * ApplicationInfo.ratio 0094 0095 spacing: 3 * ApplicationInfo.ratio 0096 0097 add: Transition { 0098 NumberAnimation { properties: "y"; duration: 1000; easing.type: Easing.OutBounce } 0099 } 0100 0101 Repeater { 0102 id: colorsRepeater 0103 0104 model: ListModel {} 0105 0106 delegate: 0107 Node { 0108 width: 40 * ApplicationInfo.ratio 0109 height: 40 * ApplicationInfo.ratio 0110 border.width: 2 0111 border.color: "white" 0112 searchItemIndex: itemIndex 0113 } 0114 } 0115 } 0116 0117 Item { 0118 id: graphRect 0119 anchors.left: parent.left 0120 anchors.leftMargin: 100 * ApplicationInfo.ratio 0121 anchors.bottom: parent.bottom 0122 anchors.bottomMargin: 50 * ApplicationInfo.ratio 0123 anchors.top: parent.top 0124 anchors.topMargin: 50 * ApplicationInfo.ratio 0125 height: background.height - 100 * ApplicationInfo.ratio 0126 width: background.width - 150 * ApplicationInfo.ratio 0127 property int diameter: graphRect.width/11 0128 property int minDiameter: 40 * ApplicationInfo.ratio 0129 property int maxDiameter: 80 * ApplicationInfo.ratio 0130 property int optDiameter: diameter < minDiameter ? minDiameter : ( diameter > maxDiameter ? maxDiameter : diameter) 0131 Repeater { 0132 id: edgesRepeater 0133 model: ListModel {} 0134 delegate: Rectangle { 0135 id: line 0136 opacity: 1 0137 antialiasing: true 0138 color: highlight == true ? "red" : "#373737" 0139 0140 transformOrigin: Item.TopLeft 0141 x: xp * graphRect.width 0142 y: yp * graphRect.height 0143 property var x2: xpp * graphRect.width 0144 property var y2: ypp * graphRect.height 0145 width: Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y- y2, 2)) 0146 height: highlight == true ? 7 * ApplicationInfo.ratio : 3 * ApplicationInfo.ratio 0147 rotation: (Math.atan((y2 - y)/(x2-x)) * 180 / Math.PI) + (((y2-y) < 0 && (x2-x) < 0) * 180) + (((y2-y) >= 0 && (x2-x) < 0) * 180) 0148 Behavior on color { 0149 ColorAnimation { 0150 duration: 2000 0151 easing.type: Easing.OutExpo 0152 } 0153 } 0154 Behavior on height { 0155 NumberAnimation { 0156 duration: 2000 0157 easing.type: Easing.OutExpo 0158 } 0159 } 0160 } 0161 0162 0163 } 0164 Repeater{ 0165 id: nodesRepeater 0166 0167 model: ListModel {} 0168 0169 delegate: 0170 Node{ 0171 id: currentNode 0172 0173 x: posX * graphRect.width - width/2 0174 y: posY * graphRect.height - height/2 0175 width: graphRect.optDiameter 0176 height: width 0177 radius: width/2 0178 border.color: highlight ? "red" : "black" 0179 border.width: highlight ? 7 : 4 0180 symbolRotation: highlight 0181 searchItemIndex: colIndex 0182 Behavior on border.color { 0183 ColorAnimation { 0184 duration: 2000 0185 easing.type: Easing.OutExpo 0186 } 0187 } 0188 0189 Behavior on border.width { 0190 NumberAnimation { 0191 duration: 2000 0192 easing.type: Easing.OutExpo 0193 } 0194 } 0195 0196 0197 MouseArea { 0198 id: mouseArea 0199 anchors.fill: parent 0200 acceptedButtons: Qt.LeftButton | Qt.RightButton 0201 enabled: !bonus.isPlaying 0202 z: 3 0203 hoverEnabled: ApplicationInfo.isMobile ? false : true 0204 0205 onClicked:{ 0206 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0207 items.currentKeyZone = chooser; 0208 items.nodeHighlight.setHighlight(index); 0209 showChooser(true, index, parent); 0210 } 0211 } 0212 states: State { 0213 name: "scaled"; when: mouseArea.containsMouse 0214 PropertyChanges { 0215 target: currentNode 0216 scale: 1.1 0217 } 0218 } 0219 transitions: Transition { 0220 NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic } 0221 } 0222 0223 } 0224 } 0225 0226 Rectangle { 0227 id: nodeHighlight 0228 z: -1 0229 width: graphRect.optDiameter * 1.5 0230 height: width 0231 radius: width * 0.5 0232 color: "#80ffffff" 0233 visible: items.currentKeyZone === graphRect && items.keyNavigationMode 0234 anchors.centerIn: nodesRepeater.itemAt(0) 0235 property int index: -1 0236 function setHighlight(toIndex) { 0237 index = toIndex; 0238 anchors.centerIn = nodesRepeater.itemAt(index); 0239 } 0240 } 0241 0242 function handleKeys(event) { 0243 if(event.key === Qt.Key_Right) { 0244 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0245 nodeHighlight.index += 1; 0246 if(nodeHighlight.index > nodesRepeater.count - 1) { 0247 nodeHighlight.index = 0; 0248 } 0249 } 0250 if(event.key === Qt.Key_Left) { 0251 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0252 nodeHighlight.index -= 1; 0253 if(nodeHighlight.index < 0) { 0254 nodeHighlight.index = nodesRepeater.count - 1; 0255 } 0256 } 0257 //if space is used before direction keys, init index at 0 0258 if(nodeHighlight.index === -1) { 0259 nodeHighlight.index = 0; 0260 } 0261 nodeHighlight.anchors.centerIn = nodesRepeater.itemAt(nodeHighlight.index); 0262 if(event.key === Qt.Key_Space) { 0263 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0264 showChooser(true, nodeHighlight.index, nodesRepeater.itemAt(nodeHighlight.index)); 0265 items.currentKeyZone = chooser; 0266 items.chooserGrid.currentIndex = 0; 0267 } 0268 } 0269 } 0270 function showChooser(visible, guessIndex, item) 0271 { 0272 if (!visible) { 0273 chooser.visible = false; 0274 return; 0275 } 0276 var modelObj = items.nodesRepeater.model.get(guessIndex); 0277 var absolute = graphRect.mapToItem(background, item.x, item.y); 0278 chooserGrid.colIndex = modelObj.colIndex; 0279 chooserGrid.guessIndex = guessIndex; 0280 var targetX = absolute.x + item.width; 0281 var targetY = absolute.y - item.height/2; 0282 if (targetX < 0) { 0283 targetX = 0; 0284 } 0285 if (targetX + chooser.width > background.width) { 0286 targetX = background.width - chooser.width - 10; 0287 } 0288 if (targetY < 0) { 0289 targetY = 0; 0290 } 0291 if (targetY + chooser.height > background.height) { 0292 targetY = background.height - chooser.height - 10; 0293 } 0294 chooser.x = targetX; 0295 chooser.y = targetY; 0296 chooser.visible = true; 0297 //console.log(" item.x = " + item.x + " item.y" + item.y+" absolute.x" + absolute.x +" absolute.y" + absolute.y) 0298 } 0299 0300 Rectangle { 0301 id: chooser 0302 0303 width: chooserGrid.width + 5 0304 height: chooserGrid.height + 5 0305 0306 color: "darkgray" 0307 border.width: 0 0308 border.color: "white" 0309 0310 opacity: 1 0311 visible: false 0312 z: 10 0313 0314 GridView { 0315 id: chooserGrid 0316 0317 cellWidth: graphRect.optDiameter - 2 0318 cellHeight: cellWidth 0319 width: Math.ceil(count / 2) * cellWidth 0320 height: 2 * cellHeight 0321 anchors.centerIn: parent 0322 z: 11 0323 0324 clip: false 0325 interactive: false 0326 verticalLayoutDirection: GridView.TopToBottom 0327 layoutDirection: Qt.LeftToRight 0328 flow: GridView.FlowLeftToRight 0329 highlight: Rectangle { 0330 color: "#80ffffff" 0331 visible: items.currentKeyZone === chooser && items.keyNavigationMode 0332 } 0333 0334 property int gridCount : count 0335 property int colIndex: 0 0336 property int guessIndex: 0 0337 0338 model: new Array() 0339 0340 delegate: Node { 0341 id: chooserItem 0342 width: graphRect.optDiameter - 5 0343 height: width 0344 border.width: index == chooserGrid.colIndex ? 3 : 1 0345 border.color: index == chooserGrid.colIndex ? "white" : "darkgray" 0346 searchItemIndex: modelData 0347 highlightSymbol: index == chooserGrid.colIndex 0348 radius: width * 0.5 0349 0350 MouseArea { 0351 id: chooserMouseArea 0352 anchors.fill: parent 0353 acceptedButtons: Qt.LeftButton 0354 enabled: !bonus.isPlaying 0355 z: 11 0356 hoverEnabled: ApplicationInfo.isMobile ? false : true 0357 0358 onClicked: { 0359 chooserGrid.colIndex = chooserItem.searchItemIndex; 0360 chooser.selectItem(); 0361 } 0362 } 0363 } 0364 } 0365 0366 function handleKeys(event) { 0367 if(event.key === Qt.Key_Right) { 0368 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0369 chooserGrid.currentIndex += 1; 0370 if(chooserGrid.currentIndex > chooserGrid.count - 1) { 0371 chooserGrid.currentIndex = 0; 0372 } 0373 } 0374 if(event.key === Qt.Key_Left) { 0375 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0376 chooserGrid.currentIndex -= 1; 0377 if(chooserGrid.currentIndex < 0) { 0378 chooserGrid.currentIndex = chooserGrid.count - 1; 0379 } 0380 } 0381 if(event.key === Qt.Key_Space) { 0382 chooserGrid.colIndex = chooserGrid.currentItem.searchItemIndex; 0383 selectItem(); 0384 } 0385 } 0386 0387 function selectItem() { 0388 activity.audioEffects.play('qrc:/gcompris/src/core/resource/sounds/smudge.wav'); 0389 var obj = items.nodesRepeater.model; 0390 obj.setProperty(chooserGrid.guessIndex, "colIndex", chooserGrid.colIndex); 0391 showChooser(false); 0392 Activity.checkAdjacent(); 0393 Activity.checkGuess(); 0394 items.currentKeyZone = graphRect; 0395 } 0396 } 0397 0398 DialogHelp { 0399 id: dialogHelp 0400 onClose: home() 0401 } 0402 0403 DialogChooseLevel { 0404 id: dialogActivityConfig 0405 currentActivity: activity.activityInfo 0406 0407 onClose: { 0408 home(); 0409 eventHandler.forceActiveFocus(); 0410 } 0411 onLoadData: { 0412 if(activityData && activityData["mode"]) { 0413 items.mode = activityData["mode"]; 0414 } 0415 } 0416 onStartActivity: { 0417 eventHandler.forceActiveFocus(); 0418 } 0419 } 0420 0421 Bar { 0422 id: bar 0423 level: items.currentLevel + 1 0424 content: BarEnumContent { value: activityConfig | help | home | level } 0425 onHelpClicked: { 0426 displayDialog(dialogHelp) 0427 } 0428 onPreviousLevelClicked: Activity.previousLevel() 0429 onNextLevelClicked: Activity.nextLevel() 0430 onHomeClicked: activity.home() 0431 onActivityConfigClicked: { 0432 displayDialog(dialogActivityConfig) 0433 } 0434 } 0435 0436 Bonus { 0437 id: bonus 0438 Component.onCompleted: win.connect(Activity.nextLevel) 0439 } 0440 } 0441 0442 }