1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the Qt Components project.
9 ** $QT_BEGIN_LICENSE:BSD$
10 ** You may use this file under the terms of the BSD license as follows:
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
15 ** * Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** * Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in
19 ** the documentation and/or other materials provided with the
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 ** the names of its contributors may be used to endorse or promote
23 ** products derived from this software without specific prior written
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
43 import "SectionScroller.js" as Sections
48 property ListView listView
51 if (listView && listView.model) {
52 internal.initDirtyObserver();
53 } else if (listView) {
54 listView.modelChanged.connect(function() {
56 internal.initDirtyObserver();
62 property Style platformStyle: SectionScrollerStyle {}
64 //Deprecated, TODO Remove this on w13
65 property alias style: root.platformStyle
71 height: listView.height
72 x: listView.x + listView.width - width
73 property bool dragging: false
77 objectName: "dragArea"
81 drag.minimumY: listView.y
82 drag.maximumY: listView.y + listView.height - tooltip.height
85 mouseDownTimer.restart()
89 container.dragging = false;
94 internal.adjustContentPosition(dragArea.mouseY);
102 container.dragging = true;
103 internal.adjustContentPosition(dragArea.mouseY);
104 tooltip.positionAtY(dragArea.mouseY);
111 opacity: container.dragging ? 1 : 0
112 anchors.right: parent.right
113 anchors.rightMargin: 50
114 width: childrenRect.width
115 height: childrenRect.height
117 function positionAtY(yCoord) {
118 tooltip.y = Math.max(dragArea.drag.minimumY, Math.min(yCoord - tooltip.height/2, dragArea.drag.maximumY));
123 width: childrenRect.width// + 20
124 height: childrenRect.height// + 20
125 anchors.left: parent.left
126 source: platformStyle.backgroundImage
127 border { left: 4; top: 4; right: 4; bottom: 4 }
130 width: Math.max(previousSectionLabel.width, currentSectionLabel.width, nextSectionLabel.width)
131 height: childrenRect.height
133 SectionScrollerLabel {
134 id: previousSectionLabel
135 objectName: "previousSectionLabel"
136 text: internal.prevSection
137 highlighted: internal.curSect === text
142 objectName: "divider1"
143 source: platformStyle.dividerImage
146 anchors.horizontalCenter: parent.horizontalCenter
149 SectionScrollerLabel {
150 id: currentSectionLabel
151 objectName: "currentSectionLabel"
152 text: internal.currentSection
153 highlighted: internal.curSect === text
158 objectName: "divider2"
159 source: platformStyle.dividerImage
162 anchors.horizontalCenter: parent.horizontalCenter
165 SectionScrollerLabel {
167 objectName: "nextSectionLabel"
168 text: internal.nextSection
169 highlighted: internal.curSect === text
180 anchors.left: background.right
181 property int threshold: currentSectionLabel.height
182 property int yInitial: background.y + background.height/2 - height/2
184 source: platformStyle.arrowImage
186 function getYPosition() {
187 var v = internal.curPos;
188 var adjust = v === "first" ? -threshold :
189 v === "last" ? threshold : 0;
191 return yInitial + adjust;
196 when: root.dragging && dragArea.mouseY < (root.listView.y + threshold)
199 y: yInitial - threshold
214 when: container.dragging
220 when: internal.curPos === "first"
222 target: previousSectionLabel
223 text: internal.currentSection
226 target: currentSectionLabel
227 text: internal.nextSection
230 target: nextSectionLabel
231 text: Sections.getNextSection(internal.nextSection)
238 when: internal.curPos === "last"
240 target: previousSectionLabel
241 text: Sections.getPreviousSection(internal.prevSection)
244 target: currentSectionLabel
245 text: internal.prevSection
248 target: nextSectionLabel
249 text: internal.currentSection
254 Behavior on opacity {
255 NumberAnimation { duration: 100 }
265 Sections.initSectionData(listView);
266 internal.modelDirty = false;
271 target: root.listView
272 onCurrentSectionChanged: internal.curSect = container.dragging ? internal.curSect : ""
278 property string prevSection: ""
279 property string currentSection: listView.currentSection
280 property string nextSection: ""
281 property string curSect: ""
282 property string curPos: "first"
284 property bool modelDirty: false
285 property bool down: true
287 function initDirtyObserver() {
288 Sections.initialize(listView);
289 function dirtyObserver() {
290 if (!internal.modelDirty) {
291 internal.modelDirty = true;
292 dirtyTimer.running = true;
296 if (listView.model.countChanged)
297 listView.model.countChanged.connect(dirtyObserver);
299 if (listView.model.itemsChanged)
300 listView.model.itemsChanged.connect(dirtyObserver);
302 if (listView.model.itemsInserted)
303 listView.model.itemsInserted.connect(dirtyObserver);
305 if (listView.model.itemsMoved)
306 listView.model.itemsMoved.connect(dirtyObserver);
308 if (listView.model.itemsRemoved)
309 listView.model.itemsRemoved.connect(dirtyObserver);
312 function adjustContentPosition(y) {
313 if (y < 0 || y > dragArea.height) return;
315 internal.down = (y > internal.oldY);
316 var sect = Sections.getClosestSection((y / dragArea.height), internal.down);
318 if (internal.curSect != sect) {
319 internal.curSect = sect;
320 internal.curPos = Sections.getSectionPositionString(internal.curSect);
321 var sec = Sections.getRelativeSections(internal.curSect);
322 internal.prevSection = sec[0];
323 internal.currentSection = sec[1];
324 internal.nextSection = sec[2];
325 var idx = Sections.getIndexFor(sect);
326 listView.positionViewAtIndex(idx, ListView.Beginning);