Commit e4a8d2b2 authored by Bruno Coudoin's avatar Bruno Coudoin
Browse files

Merge branch 'scalesboard'

parents 0960bcf4 68af05e1
......@@ -74,6 +74,8 @@ numbers-odd-even
penalty
planegame
reversecount
scalesboard
scalesboard_weight
smallnumbers
smallnumbers2
sudoku
......
......@@ -3,8 +3,8 @@ import GCompris 1.0
ActivityInfo {
name: "scalesboard/Scalesboard.qml"
difficulty: 2
icon: "scalesboard/scalesicon.svgz"
author: "miguel DE IZARRA <miguel2i@free.fr>"
icon: "scalesboard/scalesboard.svgz"
author: "Bruno Coudoin <bruno.coudoin@gcompris.net>"
demo: true
title: qsTr("Balance the scales properly")
description: qsTr("Drag and Drop weights to balance the scales")
......
GCOMPRIS_ADD_RCC(activities/scalesboard *.qml *.svg *.svgz *.js resource/*)
/* GCompris - MasseArea.qml
*
* Copyright (C) 2014 Bruno Coudoin
*
* Authors:
* Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.1
import "../../core"
import "scalesboard.js" as Activity
Rectangle {
id: masseArea
height: itemHeight
color: dropArea.containsDrag ? "#33333333" : "#00000000"
border.width: 2
border.color: dropArea.containsDrag ? "#33666666" : "#00000000"
property int nbColumns
property int nbLines: background.width > background.height ? 1 : 2
property int itemWidth: (width - masseFlow.spacing * nbColumns) / nbColumns
property int itemHeight: itemWidth * 1.2
property Item masseAreaCenter
property Item masseAreaLeft
property Item masseAreaRight
property alias masseModel: masseModel
property alias dropArea: dropArea
property int weight: 0
function init() {
weight = 0
masseModel.clear()
}
function removeWeight(value) {
weight -= value
}
function removeMasse(masseArea, index, weight) {
masseArea.removeWeight(weight)
masseArea.masseModel.remove(index)
}
function addMasse(img, weight, index, dragEnabled) {
masseModel.append( {
img: img,
weight: weight,
masseIndex: index,
opacity: 1.0,
dragEnabled: dragEnabled
} )
masseArea.weight += weight
}
function showMasseInMasseArea(index) {
masseAreaCenter.masseModel.get(index).opacity = 1.0
}
function hideMasseInMasseArea(index) {
masseAreaCenter.masseModel.get(index).opacity = 0.0
}
ListModel {
id: masseModel
}
DropArea {
id: dropArea
anchors.fill: parent
}
Flow {
id: masseFlow
anchors.topMargin: 4
anchors.bottomMargin: 4
anchors.fill: parent
spacing: 10
flow: Flow.TopToBottom
add: Transition {
NumberAnimation {
properties: "x"
from: parent.width * 0.05
easing.type: Easing.InOutQuad
}
}
move: Transition {
NumberAnimation {
properties: "x,y"
easing.type: Easing.InOutQuad
}
}
Repeater {
id: answer
model: masseModel
Image {
source: Activity.url + img
sourceSize.height: masseArea.itemHeight
height: masseArea.itemHeight
opacity: model.opacity
property string img: model.img
property int masseIndex: model.masseIndex
property int modelIndex: index
property int weight: model.weight
property int masseOriginX
property int masseOriginY
property int originX
property int originY
property Item currentMasseArea: masseArea
Drag.active: dragArea.drag.active
Drag.hotSpot.x: width / 2
Drag.hotSpot.y: height / 2
function initDrag() {
originX = x
originY = y
if(currentMasseArea == masseArea) {
masseOriginX = x
masseOriginY = y
}
z = 111
}
function replace() {
x = originX
y = originY
}
function replaceInMasse() {
x = masseOriginX
y = masseOriginY
}
onOpacityChanged: opacity == 1.0 ? currentMasseArea = masseAreaCenter : null
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: parent
enabled: model.dragEnabled
onPressed: {
parent.initDrag()
}
function dropOnPlate(masseArea) {
parent.Drag.cancel()
if(parent.currentMasseArea == masseAreaCenter) {
masseArea.hideMasseInMasseArea(parent.masseIndex)
parent.replaceInMasse()
}
masseArea.addMasse(parent.img,
parent.weight,
parent.masseIndex,
/* dragEnabled */ true)
if(parent.currentMasseArea != masseAreaCenter) {
removeMasse(parent.currentMasseArea,
parent.modelIndex, parent.weight)
}
parent.currentMasseArea = masseArea
}
onReleased: {
if(masseAreaLeft.dropArea.containsDrag &&
parent.currentMasseArea != masseAreaLeft) {
dropOnPlate(masseAreaLeft)
} else if (masseAreaRight.dropArea.containsDrag &&
parent.currentMasseArea != masseAreaRight) {
dropOnPlate(masseAreaRight)
} else if (masseAreaCenter.dropArea.containsDrag &&
parent.dropArea != masseAreaCenter){
parent.Drag.cancel()
masseAreaCenter.showMasseInMasseArea(parent.masseIndex)
parent.replaceInMasse()
if(parent.currentMasseArea != masseAreaCenter) {
removeMasse(parent.currentMasseArea,
parent.modelIndex, parent.weight)
}
} else {
parent.Drag.cancel()
parent.replace()
}
}
}
Text {
anchors.fill: parent
text: model.weight
font.pointSize: 18
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
}
Behavior on y {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
}
/* GCompris - Scalesboard.qml
*
* Copyright (C) 2014 Bruno Coudoin
*
* Authors:
* miguel DE IZARRA <miguel2i@free.fr> (GTK+ version)
* Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.1
import "../../core"
import "scalesboard.js" as Activity
ActivityBase {
id: activity
onStart: focus = true
onStop: {}
pageComponent: Rectangle {
id: background
anchors.fill: parent
color: "#ABCDEF"
signal start
signal stop
property int scaleHeight: items.masseAreaLeft.weight == items.masseAreaRight.weight ? 0 :
items.masseAreaLeft.weight > items.masseAreaRight.weight ? 20 : -20
Component.onCompleted: {
activity.start.connect(start)
activity.stop.connect(stop)
}
// Add here the QML items you need to access in javascript
QtObject {
id: items
property Item main: activity.main
property alias background: background
property alias bar: bar
property alias bonus: bonus
property alias masseAreaCenter: masseAreaCenter
property alias masseAreaLeft: masseAreaLeft
property alias masseAreaRight: masseAreaRight
property alias masseCenterModel: masseAreaCenter.masseModel
property alias masseRightModel: masseAreaRight.masseModel
}
onStart: { Activity.start(items) }
onStop: { Activity.stop() }
onScaleHeightChanged: Activity.initCompleted && scaleHeight == 0 ? bonus.good("flower") : null
Image {
id: scale
source: Activity.url + "scale.svg"
sourceSize.width: parent.width * 0.8
anchors.centerIn: parent
}
Image {
id: needle
parent: scale
source: Activity.url + "needle.svg"
sourceSize.width: parent.width * 0.75
z: -10
property int angle: - background.scaleHeight * 0.35
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
verticalCenterOffset: - parent.paintedHeight * 0.15
}
transform: Rotation {
origin.x: needle.width / 2
origin.y: needle.height * 0.9
angle: needle.angle
}
Behavior on angle {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
}
// === The Left plate ===
Image {
id: plateLeft
parent: scale
source: Activity.url + "plate.svg"
sourceSize.width: parent.width * 0.35
z: -1
anchors {
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: - parent.paintedWidth * 0.3
verticalCenter: parent.verticalCenter
verticalCenterOffset: - parent.paintedHeight * 0.03 + background.scaleHeight
}
Behavior on anchors.verticalCenterOffset {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
// The Left Drop Area
MasseArea {
id: masseAreaLeft
parent: scale
height: itemHeight
width: plateLeft.width
anchors {
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: - parent.paintedWidth * 0.3
verticalCenter: parent.verticalCenter
verticalCenterOffset: - parent.paintedHeight * 0.4 + background.scaleHeight
}
masseAreaCenter: masseAreaCenter
masseAreaLeft: masseAreaLeft
masseAreaRight: masseAreaRight
nbColumns: 4
Behavior on anchors.verticalCenterOffset {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
}
}
// === The Right plate ===
Image {
id: plateRight
parent: scale
source: Activity.url + "plate.svg"
sourceSize.width: parent.width * 0.35
z: -1
anchors {
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: parent.paintedWidth * 0.3
verticalCenter: parent.verticalCenter
verticalCenterOffset: - parent.paintedHeight * 0.03 - background.scaleHeight
}
Behavior on anchors.verticalCenterOffset {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
// The Right Drop Area
MasseArea {
id: masseAreaRight
parent: scale
height: itemHeight
width: plateRight.width
anchors {
horizontalCenter: parent.horizontalCenter
horizontalCenterOffset: parent.paintedWidth * 0.3
verticalCenter: parent.verticalCenter
verticalCenterOffset: - parent.paintedHeight * 0.4 - background.scaleHeight
}
masseAreaCenter: masseAreaCenter
masseAreaLeft: masseAreaLeft
masseAreaRight: masseAreaRight
nbColumns: 4
Behavior on anchors.verticalCenterOffset {
NumberAnimation {
duration: 500
easing.type: Easing.InOutQuad
}
}
}
}
// === The Initial Masses List ===
MasseArea {
id: masseAreaCenter
parent: scale
x: parent.width * 0.05
y: parent.height * 0.86 - height
width: parent.width
masseAreaCenter: masseAreaCenter
masseAreaLeft: masseAreaLeft
masseAreaRight: masseAreaRight
nbColumns: masseModel.count / nbLines
}
DialogHelp {
id: dialogHelp
onClose: home()
}
Bar {
id: bar
content: BarEnumContent { value: help | home | previous | next }
onHelpClicked: {
displayDialog(dialogHelp)
}
onPreviousLevelClicked: Activity.previousLevel()
onNextLevelClicked: Activity.nextLevel()
onHomeClicked: activity.home()
}
Bonus {
id: bonus
Component.onCompleted: win.connect(Activity.nextSubLevel)
}
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2"
sodipodi:docname="masse1.svg"
viewBox="0 0 369.45015 505.67333"
sodipodi:version="0.32"
version="1.0"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:version="0.48.4 r9939"
width="100%"
height="100%">
<defs
id="defs4">
<linearGradient
id="linearGradient11719">
<stop
id="stop11721"
style="stop-color:black;stop-opacity:0"
offset="0" />
<stop
id="stop11723"
style="stop-color:black;stop-opacity:0"
offset="0.6" />
<stop
id="stop11725"
style="stop-color:black"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient1400">
<stop
id="stop1401"
style="stop-color:#000000;stop-opacity:.67843"
offset="0" />
<stop
id="stop1403"
style="stop-color:#000000;stop-opacity:.32941"
offset="0.57" />
<stop
id="stop1402"
style="stop-color:#000000;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
id="radialGradient21522"
xlink:href="#linearGradient11719"
gradientUnits="userSpaceOnUse"
cy="434.73999"
cx="387.81"
gradientTransform="matrix(1.4518,0,0,3.3816673,-163.82318,-1032.5506)"
r="14.312"
inkscape:collect="always" />
<radialGradient
id="radialGradient21524"
xlink:href="#linearGradient11719"
gradientUnits="userSpaceOnUse"
cy="434.73999"
cx="385.75"
gradientTransform="matrix(0,2.365,-3.6526,0,1986.9152,-478.57773)"
r="14.312"
inkscape:collect="always" />
<radialGradient
id="radialGradient21534"
xlink:href="#linearGradient1400"
gradientUnits="userSpaceOnUse"
cy="331.67001"
cx="508.64001"
gradientTransform="matrix(0,-0.07219949,0.23306,0,321.32,453.81663)"
r="17.922001"
inkscape:collect="always" />
<radialGradient
id="radialGradient21542"
xlink:href="#linearGradient11719"
gradientUnits="userSpaceOnUse"
cy="420.14001"
cx="387.19"
gradientTransform="matrix(1.4598,0,0,2.845,-166.65,-772.85)"
r="4.1875"
inkscape:collect="always" />
<radialGradient
id="radialGradient21544"
xlink:href="#linearGradient1400"
gradientUnits="userSpaceOnUse"
cy="425.85001"
cx="387.81"
gradientTransform="matrix(1,0,0,0.14249821,11.307682,372.80574)"
r="14.312"
inkscape:collect="always" />
<radialGradient
id="radialGradient21546"
gradientUnits="userSpaceOnUse"
cy="432.67001"
cx="387.81"
gradientTransform="matrix(1.4877,0,0,0.22616559,-177.82832,336.31579)"
r="14.312"
inkscape:collect="always"
xlink:href="#linearGradient11719">
<stop
id="stop5148"
style="stop-color:white;stop-opacity:0"
offset="0" />
<stop
id="stop5150"
style="stop-color:white;stop-opacity:0"
offset="0.6" />
<stop
id="stop5152"
style="stop-color:white"
offset="1" />
</radialGradient>
<radialGradient
id="radialGradient21548"
xlink:href="#linearGradient11719"
gradientUnits="userSpaceOnUse"
cy="434.73999"
cx="385.75"
gradientTransform="matrix(0.0016095,1.368961,-4.5719,0.00162108,2386.1,-106.61411)"