1/* GCompris - List.qml
2 *
3 * SPDX-FileCopyrightText: 2014 Arkit Vora <arkitvora123@gmail.com>
4 *
5 * Authors:
6 *   <Srishti Sethi> (GTK+ version)
7 *   Arkit Vora <arkitvora123@gmail.com> (Qt Quick port)
8 *
9 *   SPDX-License-Identifier: GPL-3.0-or-later
10 */
11import QtQuick 2.9
12import GCompris 1.0
13
14import "../../core"
15import "louis-braille.js" as Activity
16
17Rectangle {
18    id: wholeBody
19    width: parent.width
20    height: parent.height
21    color: "#ff55afad"
22
23    property color goodColor: colorMode ?  "#ffc1ffb4" : "#FFF"
24    property color badColor: colorMode ?  "#FFF" : "#FFF"
25    property bool colorMode: true
26    property Item bonus
27    property int selectedIndex: -1
28    property alias containerModel: list.model
29    property int listPix: wholeBody.height /30
30
31    signal up
32    signal down
33    signal space
34
35    onUp: list.decrementCurrentIndex()
36    onDown: list.incrementCurrentIndex()
37    onSpace: {
38        if(list.currentIndex == selectedIndex) {
39            selectedIndex = -1
40        } else if(selectedIndex != -1) {
41            containerModel.move(selectedIndex, list.currentIndex, 1)
42            list.currentIndex -= 1
43            selectedIndex = -1
44        } else {
45            selectedIndex = list.currentIndex
46        }
47    }
48
49    function checkWin() {
50        var win = true
51        // The shifted numbering comes from the header in the List
52        for(var i = 1; i < list.count + 1; i++) {
53            if(!list.contentItem.children[i] ||
54                list.contentItem.children[i].placed === false)
55                win = false
56        }
57        if(win) {
58            list.currentIndex = -1
59            bonus.good("tux")
60        }
61    }
62
63    Component {
64        id: listElement
65
66        Rectangle {
67            id: listRect
68            color: wholeBody.selectedIndex == index ? "#b5b9ff" : (placed ? goodColor : badColor)
69            border.width: list.currentIndex == index ? 0 : 1
70            border.color: "#ff525c5c"
71            radius: 3
72            width: list.width
73            height: Math.max(textinfo.height * 1.3, 50 * ApplicationInfo.ratio)
74
75            property int sequence: model.sequence
76            property bool placed: model.sequence === index
77            property string text: model.text
78
79            SequentialAnimation {
80                id: borderAnim
81                running: list.currentIndex == index
82                loops: Animation.Infinite
83                NumberAnimation {
84                    target: listRect
85                    property: "border.width"
86                    to: 5; duration: 500
87                    easing.type: Easing.InOutQuad
88                }
89                NumberAnimation {
90                    target: listRect
91                    property: "border.width"
92                    to: 0; duration: 500
93                    easing.type: Easing.InOutQuad
94                }
95            }
96
97            GCText {
98                id: textinfo
99                text: listRect.text
100                anchors.centerIn: parent
101                horizontalAlignment: Text.AlignHCenter
102                width: parent.width * 0.94
103                wrapMode: Text.WordWrap
104                font.pixelSize: listPix
105            }
106
107            MouseArea {
108                id: dragArea
109                anchors.fill: parent
110                onClicked: {
111                    wholeBody.selectedIndex = -1
112                    if(list.currentIndex == index) {
113                        list.currentIndex = -1
114                    } else if(list.currentIndex == -1) {
115                        list.currentIndex = index
116                    } else {
117                        containerModel.move(list.currentIndex, index, 1)
118                        list.currentIndex = -1
119                    }
120                }
121            }
122
123            Behavior on color {
124                ColorAnimation {
125                    duration: 200
126                }
127            }
128
129        }
130    }
131
132    ListModel {
133        id: containerModel
134    }
135
136    ListView {
137        id: list
138        anchors {
139            fill: parent
140            bottomMargin: bar.height*1.5 + listScrollerB.height+20
141            leftMargin: 30 * ApplicationInfo.ratio
142            rightMargin: 30 * ApplicationInfo.ratio
143            topMargin: 10 * ApplicationInfo.ratio
144        }
145        width: parent.width * 0.7
146        model: containerModel
147        spacing: 5 * ApplicationInfo.ratio
148        delegate: listElement
149        interactive: true
150
151        header: Rectangle {
152            width: parent.width
153            height: heading.height + 10
154            color: "#cceaeaea"
155            GCText {
156                id: heading
157                text: qsTr("Arrange the events in the order in which they happened. " +
158                           "Select the line to move, then select its target position.")
159                width: parent.width - 4
160                wrapMode: Text.WordWrap
161                horizontalAlignment: Text.AlignHCenter
162                font.pointSize: NaN
163                font.pixelSize: listPix
164            }
165        }
166        onCurrentIndexChanged: timer.restart()
167        displaced: Transition {
168            NumberAnimation { properties: "y"; duration: 500 }
169        }
170        move: Transition {
171            NumberAnimation { properties: "y"; duration: 500 }
172        }
173        Component.onCompleted: currentIndex = -1
174    }
175
176    GCButtonScroll {
177        id:listScrollerB
178        upVisible: list.visibleArea.yPosition <= 0 ? 0 : 1
179        downVisible: list.visibleArea.yPosition + list.visibleArea.heightRatio >= 1 ? 0 : 1
180        anchors {
181            bottom: parent.bottom
182            bottomMargin: bar.height +10
183            horizontalCenter: parent.horizontalCenter
184        }
185        isHorizontal: true
186        onUp: list.flick(0,700)
187        onDown: list.flick(0,-700)
188
189    }
190
191    Timer {
192        id: timer
193        interval: 1000
194        running: false
195        repeat: false
196        onTriggered: wholeBody.checkWin()
197    }
198}
199