18 import Ubuntu.Components 0.1
19 import
"carousel.js" as CarouselJS
30 property Component itemComponent
32 property alias model: listView.model
34 property alias minimumTileWidth: listView.minimumTileWidth
36 property alias pathItemCount: listView.pathItemCount
38 property alias tileAspectRatio: listView.tileAspectRatio
40 property alias cacheBuffer: listView.cacheBuffer
45 property int drawBuffer: width / pathItemCount
47 property real selectedItemScaleFactor: 1.1
49 property alias highlightIndex: listView.highlightIndex
51 readonly
property alias currentItem: listView.currentItem
53 readonly
property alias verticalSpacing: listView.verticalMargin
58 signal clicked(
int index, real itemY)
61 signal pressAndHold(
int index, real itemY)
65 implicitHeight: listView.tileHeight * selectedItemScaleFactor
66 opacity: listView.highlightIndex === -1 ? 1 : 0.6
78 objectName:
"listView"
80 property int highlightIndex: -1
81 property real minimumTileWidth: 0
82 property real newContentX: disabledNewContentX
83 property real pathItemCount: referenceWidth / referenceTileWidth
84 property real tileAspectRatio: 1
104 readonly
property real gapToMiddlePhase: Math.min(realWidth / 2 - tileWidth / 2, (realContentWidth - realWidth) / 2)
105 readonly
property real gapToEndPhase: realContentWidth - realWidth - gapToMiddlePhase
106 readonly
property real kGapEnd: kMiddleIndex * (1 - gapToEndPhase / gapToMiddlePhase)
107 readonly property real kMiddleIndex: (realWidth / 2) / tileWidth - 0.5
108 readonly
property real kXBeginningEnd: 1 / tileWidth + kMiddleIndex / gapToMiddlePhase
109 readonly
property real maximumItemTranslation: (listView.tileWidth * 3) / listView.scaleFactor
110 readonly property real disabledNewContentX: -carousel.drawBuffer - 1
111 readonly property real realContentWidth: contentWidth - 2 * carousel.drawBuffer
112 readonly property real realContentX: contentX + carousel.drawBuffer
113 readonly property real realPathItemCount: Math.min(realWidth / tileWidth, pathItemCount)
114 readonly
property real realWidth: carousel.width
115 readonly
property real referenceGapToMiddlePhase: realWidth / 2 - tileWidth / 2
116 readonly
property real referencePathItemCount: referenceWidth / referenceTileWidth
117 readonly
property real referenceWidth: 848
118 readonly
property real referenceTileWidth: 175
119 readonly
property real scaleFactor: tileWidth / referenceTileWidth
120 readonly
property real tileWidth: Math.max(realWidth / pathItemCount, minimumTileWidth)
121 readonly
property real tileHeight: tileWidth / tileAspectRatio
122 readonly
property real translationXViewFactor: 0.2 * (referenceGapToMiddlePhase / gapToMiddlePhase)
123 readonly property real verticalMargin: (parent.height - tileHeight) / 2
124 readonly
property real visibleTilesScaleFactor: realPathItemCount / referencePathItemCount
128 topMargin: verticalMargin
129 bottomMargin: verticalMargin
131 leftMargin: -carousel.drawBuffer
132 rightMargin: -carousel.drawBuffer
138 width: carousel.drawBuffer
139 height: listView.tileHeight
142 width: carousel.drawBuffer
143 height: listView.tileHeight
146 boundsBehavior: Flickable.DragOverBounds
147 cacheBuffer: carousel.cacheBuffer
148 flickDeceleration: Math.max(1500 * Math.pow(realWidth / referenceWidth, 1.5), 1500)
149 maximumFlickVelocity: Math.max(2500 * Math.pow(realWidth / referenceWidth, 1.5), 2500)
150 orientation: ListView.Horizontal
152 function getXFromContinuousIndex(index) {
153 return CarouselJS.getXFromContinuousIndex(index,
162 function itemClicked(index, delegateItem) {
163 listView.currentIndex = index
164 var x = getXFromContinuousIndex(index);
166 if (Math.abs(x - contentX) < 1 && delegateItem !== undefined) {
170 carousel.clicked(index, delegateItem.y)
175 newContentXAnimation.stop()
178 newContentXAnimation.start()
181 function itemPressAndHold(index, delegateItem) {
182 var x = getXFromContinuousIndex(index);
184 if (Math.abs(x - contentX) < 1 && delegateItem !== undefined) {
188 carousel.pressAndHold(index, delegateItem.y);
192 stepAnimation.stop();
193 newContentXAnimation.stop();
196 newContentXAnimation.start();
199 onHighlightIndexChanged: {
200 if (highlightIndex != -1) {
201 itemClicked(highlightIndex)
207 newContentXAnimation.stop()
208 newContentX = disabledNewContentX
211 if (realContentX > 0)
212 stepAnimation.start()
217 objectName:
"stepAnimation"
221 to: listView.getXFromContinuousIndex(listView.selectedIndex)
224 easing.type: Easing.InOutQuad
227 SequentialAnimation {
228 id: newContentXAnimation
233 from: listView.contentX
234 to: listView.newContentX
236 easing.type: Easing.InOutQuad
239 script: listView.newContentX = listView.disabledNewContentX
243 readonly
property int selectedIndex: Math.round(continuousIndex)
244 readonly
property real continuousIndex: CarouselJS.getContinuousIndex(listView.realContentX,
246 listView.gapToMiddlePhase,
247 listView.gapToEndPhase,
249 listView.kMiddleIndex,
250 listView.kXBeginningEnd)
252 property real viewTranslation: CarouselJS.getViewTranslation(listView.realContentX,
254 listView.gapToMiddlePhase,
255 listView.gapToEndPhase,
256 listView.translationXViewFactor)
258 delegate: tileWidth > 0 && tileHeight > 0 ? loaderComponent : undefined
264 property bool explicitlyScaled: explicitScaleFactor == carousel.selectedItemScaleFactor
265 property real explicitScaleFactor: explicitScale ? carousel.selectedItemScaleFactor : 1.0
266 readonly
property bool explicitScale: (!listView.moving ||
267 listView.realContentX <= 0 ||
268 listView.realContentX >= listView.realContentWidth - listView.realWidth) &&
269 listView.newContentX === listView.disabledNewContentX &&
270 index === listView.selectedIndex
271 readonly property real cachedTiles: listView.realPathItemCount + carousel.drawBuffer / listView.tileWidth
272 readonly property real distance: listView.continuousIndex - index
273 readonly property real itemTranslationScale: CarouselJS.getItemScale(0.5,
276 listView.visibleTilesScaleFactor)
277 readonly
property real itemScale: CarouselJS.getItemScale(distance,
278 listView.continuousIndex,
280 listView.visibleTilesScaleFactor)
281 readonly
property real translationX: CarouselJS.getItemTranslation(index,
282 listView.selectedIndex,
285 itemTranslationScale,
286 listView.maximumItemTranslation)
288 readonly
property real xTransform: listView.viewTranslation + translationX * listView.scaleFactor
289 readonly
property real center: x - listView.contentX + xTransform - drawBuffer + (width/2)
291 width: listView.tileWidth
292 height: listView.tileHeight
293 scale: itemScale * explicitScaleFactor
294 sourceComponent: itemComponent
295 z: cachedTiles - Math.abs(index - listView.selectedIndex)
297 transform: Translate {
301 Behavior on explicitScaleFactor {
302 SequentialAnimation {
304 script:
if (!explicitScale)
305 explicitlyScaled =
false
308 duration: explicitScaleFactor === 1.0 ? 250 : 150
309 easing.type: Easing.InOutQuad
312 script:
if (explicitScale)
313 explicitlyScaled =
true
319 item.explicitlyScaled = Qt.binding(
function() {
return explicitlyScaled; })
320 item.model = Qt.binding(
function() {
return model; })
329 listView.itemClicked(index, item)
333 listView.itemPressAndHold(index, item)