stateslist.qml 12.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import Qt 4.6

// Shows list of states
// the model has to expose the path through an iconUrl property
Rectangle {
    id: root
    property int currentStateIndex : 0
    signal createNewState
    signal deleteCurrentState
    signal duplicateCurrentState

    color: "#707070";

    function adjustCurrentStateIndex() {
        if (currentStateIndex >= statesEditorModel.count)
            currentStateIndex = statesEditorModel.count-1;
    }

    Connection {
        sender: statesEditorModel
        signal: "countChanged()"
        script: adjustCurrentStateIndex();
    }

    Connection {
        sender: statesEditorModel
        signal: "changedToState(n)"
        script: {root.currentStateIndex = n}
    }
30
31
32

    // TextInputs don't loose focus automatically when user clicks away, have to be done explicitly
    signal unFocus
33
34
35
36
37
38
    MouseRegion {
        anchors.fill:parent
        hoverEnabled:true
        onExited: root.unFocus();
    }

39
40
41
42
43
44
45
46

    Flickable {
        id: listView

        anchors.fill: root;

        anchors.bottomMargin: 10;
        anchors.topMargin: 2;
47
48
        anchors.leftMargin: 2;
        anchors.rightMargin: 2;
49
50

        viewportHeight: height
51
        viewportWidth: statesRow.width+2
52
53

        Row {
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
            id: statesRow
            spacing:4
            Row {
                id: listViewRow
                spacing: 4
                Repeater {
                    model: statesEditorModel
                    delegate: Delegate
                }
            }
            Loader {
                sourceComponent: newStateBox;
                // make it square
                width: height
                height: listViewRow.height - 21
                y:18
                id: newStateBoxLoader;
71
            }
72
73


74
75
76
77
78
79
80
81
82
83
84
85
86
        }

        focus: true;
        clip: true;
        overShoot: false;
        interactive:false;

    }

    Component {
        id: Delegate
        Item {
            id: container
87
            width: Math.max(img.width, txt.width+removeState.width+2,stateNameEditor.width) + 4
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
            height: img.height + txt.height + 4

            Rectangle {
                id: Highlight
                anchors.fill: parent
                color: "#0303e0"
                radius: 4
                opacity: (index==root.currentStateIndex);
                onOpacityChanged: if (opacity) {
                    // If the current item becomes selected, check if it is in the viewport
                    if (container.x < listView.viewportX)
                        horizontalScrollbar.viewPosition = container.x;
                    if (container.x+container.width > listView.viewportX + listView.width)
                        horizontalScrollbar.viewPosition = container.x+container.width - listView.width;
                }
            }

            Image {
                id: img
                pixmap: statePixmap
                anchors.horizontalCenter: parent.horizontalCenter
109
                anchors.top: textLimits.bottom
110
111
112
113
114
115
116
117
                anchors.topMargin: 2
            }

            MouseRegion {
                id: itemRegion
                anchors.fill: container
                onClicked: {
                    root.currentStateIndex = index
118
                    root.unFocus();
119
120
121
                }
            }

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160


            // The erase button
            Rectangle {
                id: removeState

                visible: { index != 0 }

                anchors.right: parent.right
                anchors.top: parent.top
                anchors.topMargin: 4;
                anchors.rightMargin:2;

                width: 12
                height: width

                color: "#AEAEAE"
                radius: 6

                // "clicked" overlay
                Rectangle {
                    anchors.fill:parent
                    opacity:parent.state=="Pressed"
                    color: "#909090"
                    radius: parent.radius
                }

                states: State{ name: "Pressed"; }

                // "minus" sign
                Rectangle {
                    width: parent.width - 4;
                    height:2
                    color:(root.currentStateIndex==index?Highlight.color:root.color);
                    anchors.centerIn:parent
                }



161
162
163
                MouseRegion {
                    anchors.fill:parent
                    onClicked: {
164
                        var oldindex = root.currentStateIndex;
165
                        root.currentStateIndex = index;
166
                        root.unFocus();
167
168
169
170
171
                        root.deleteCurrentState();
                        root.currentStateIndex = oldindex;
                        if (root.currentStateIndex >= statesEditorModel.count)
                            root.currentStateIndex = root.currentStateIndex-1;
                        horizontalScrollbar.totalLengthDecreased();
172
                    }
173
174
175
                    onPressed: {parent.state="Pressed"}
                    onReleased: {parent.state=""}

176
177
                }
            }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

            Connection {
                sender: root
                signal: "unFocus()"
                script: stateNameEditor.unFocus()
            }

            Item {
                id: textLimits
                anchors.top: parent.top
                anchors.left:parent.left
                anchors.right:removeState.left
                height: txt.height
                clip: false

                Text{
                    anchors.top: parent.top
                    anchors.topMargin: 2
                    anchors.horizontalCenter: textLimits.horizontalCenter
                    id: txt
                    text: stateName
                    color: "#E1E1E1";
200
201
202
203
204
205
206
207
                    }
                MouseRegion {
                    id: txtRegion
                    anchors.fill:parent
                    onClicked: {
                        if (root.currentStateIndex != index)
                            root.unFocus();
                        root.currentStateIndex = index;
208

209
210
211
212
213
214
                    }
                    onDoubleClicked: if (index!=0) {
                        stateNameInput.text=stateName;
                        stateNameInput.focus=true;
                        stateNameEditor.visible=true;
                        stateNameInput.cursorVisible=true;
215
216
217
                    }
                }

218

219
220
221
222
223
224
225
                Rectangle {
                    id:stateNameEditor
                    visible:false

                    x:2
                    y:2
                    height:parent.height
226
                    width:Math.max(img.width,txt.width+removeState.width+2,transparentText.width+16)
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
                    clip:true

                    color:"white"
                    border.width:2
                    border.color:"#8f8f8f"
                    radius:4
                    function unFocus() {
                        if (visible)
                            statesEditorModel.renameState(index,stateNameInput.text);
                        visible=false;
                    }

                    MouseRegion {
                        id: AbsorbAllClicks
                        anchors.fill:parent
                    }
243
244
245
246
247
                    Text {
                        text:stateNameInput.text
                        visible:false
                        id:transparentText
                    }
248
249
250
                    TextInput {
                        id:stateNameInput
                        text:stateName
251
252
                        anchors.fill:parent
                        anchors.leftMargin:8
253
254
255
256
257
258
259
260
261
262
263
                        onAccepted: {
                            statesEditorModel.renameState(index,text);
                            parent.visible=false;
                        }

                    }

                }
            }


264
265
266
267
        }
    }


268
269
270
271
272
273
274
    Component {
        id: newStateBox
        Rectangle {
            anchors.fill: parent
            color: "transparent"
            border.width: 1
            border.color: "#4F4F4F"
275

276
277
278
            Loader {
                sourceComponent: addState
                anchors.fill: parent
279
280
281

            }
        }
282
    }
283

284
285
    Rectangle {
        id: floatingNewStateBox
286

287
288
289
290
291
292
293
294
295
        color: root.color
        border.width: 1
        border.color: "#4F4F4F"
        width: 40
        height: 40
        anchors.bottom:horizontalScrollbar.top
        anchors.right:root.right
        anchors.bottomMargin:1
        anchors.rightMargin:1
296

297
298
299
300
301
302
        visible:(newStateBoxLoader.x+newStateBoxLoader.width/2-11>listView.width+listView.viewportX);


        Loader {
            sourceComponent: addState
            anchors.fill: parent
303
304
305
306
307
        }
    }



308
309
310
311
312
313
    // The add button
    Component {
        id: addState
        Item {
            anchors.fill:parent
            Rectangle {
314

315
                anchors.centerIn: parent
316

317
318
                width: 21
                height: width
319

320
321
                color:"#4F4F4F"
                radius: width/2
322

323
324
325
326
327
328
329
                // "clicked" overlay
                Rectangle {
                    anchors.fill:parent
                    opacity:parent.state=="Pressed"
                    color : "#282828"
                    radius: parent.radius
                }
330

331
                states: State{ name: "Pressed"; }
332

333
334
335
336
337
338
339
340
341
342
343
344
345
                // "plus" sign
                Rectangle {
                    width:parent.width-10
                    height:3
                    color:root.color
                    anchors.centerIn:parent
                }
                Rectangle {
                    width:3
                    height:parent.height-10
                    color:root.color
                    anchors.centerIn:parent
                }
346
347
348
349
350
351
            }
            MouseRegion {
                anchors.fill:parent
                onClicked: {
                    root.unFocus();
                    if (root.currentStateIndex == 0)
352
                        root.createNewState(); //create new state
353
                    else
354
                        root.duplicateCurrentState(); //duplicate current state
355
356
357
358
359
360
361

                    listView.viewportX = horizontalScrollbar.viewPosition;
                    // select the newly created state
                    root.currentStateIndex=statesEditorModel.count - 1;
                }
                onPressed: {parent.state="Pressed"}
                onReleased: {parent.state=""}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
            }
        }
    }

    Item {
        id: horizontalScrollbar
        // Current listView implementation sometimes has negative width or viewportWidth
        property int viewPosition: 0;
        property int viewLength: ( listView.width>=0 ? listView.width : 0 );
        property int totalLength: ( listView.viewportWidth>=0 ? listView.viewportWidth : 0 );


        onViewPositionChanged: listView.viewportX=viewPosition;
        onViewLengthChanged: {
            if ((totalLength>viewLength) && (viewPosition > totalLength-viewLength))
                viewPosition = totalLength-viewLength;
        }

        function totalLengthDecreased()  {
            if ((totalLength>viewLength) && (viewPosition > totalLength-viewLength))
                viewPosition = totalLength-viewLength;
        }

        opacity: viewLength < totalLength;

        anchors.left : listView.left
        anchors.right : listView.right
        anchors.bottom : root.bottom
        anchors.bottomMargin: 4

        height: 10;

        // the bar itself
        Item {
            id: draggableBar
397
398
399
400
            width: if (horizontalScrollbar.totalLength>0) {
                if (horizontalScrollbar.viewLength>horizontalScrollbar.totalLength) parent.width;
                else horizontalScrollbar.viewLength/horizontalScrollbar.totalLength  * parent.width;
            } else 0;
401
            height: parent.height;
402
            x: (horizontalScrollbar.totalLength>0?horizontalScrollbar.viewPosition*horizontalScrollbar.width/horizontalScrollbar.totalLength:0);
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419


            Rectangle {
                height:parent.height-1
                width:parent.width
                y:1

                gradient: Gradient {
                    GradientStop { position: 0.0; color: "#C6C6C6" }
                    GradientStop { position: 1.0; color: "#7E7E7E" }
                }
            }

            MouseRegion {
                anchors.fill:parent
                property int dragging:0;
                property int originalX:0;
420
                onPressed: { dragging = 1; originalX = mouse.x;root.unFocus(); }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
                onReleased: { dragging = 0; }
                onPositionChanged: if (dragging)
                {
                    var newX = mouse.x - originalX + parent.x;
                    if (newX<0) newX=0;
                    if (newX>horizontalScrollbar.width-draggableBar.width)
                        newX=horizontalScrollbar.width-draggableBar.width;
                    horizontalScrollbar.viewPosition = newX*horizontalScrollbar.totalLength/horizontalScrollbar.width;
                }
            }
        }

        // border
        Rectangle {
            anchors.fill:parent;
            color:"Transparent";
            border.width:1;
            border.color:"#8F8F8F";
        }

    }

}