2 * Copyright (C) 2014,2015 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import Ubuntu.Components 1.3
19 import "../../Components"
21 /*! \brief Preview widget for rating display.
23 The widget can show a rating widget and a field showing a comment.
24 The icons used in the rating widget can be customised with
25 widgetData["rating-icon-empty"], widgetData["rating-icon-full"]
26 and widgetData["rating-icon-half"].
28 This widget shows reviews contained in widgetData["reviews"], each of which should be of the form:
41 implicitHeight: childrenRect.height
43 onParentFlickableChanged: ratingsList.updateRanges();
46 target: parentFlickable
47 onOriginYChanged: ratingsList.updateRanges();
48 onContentYChanged: ratingsList.updateRanges();
49 onHeightChanged: ratingsList.updateRanges();
50 onContentHeightChanged: ratingsList.updateRanges();
55 anchors { left: parent.left; right: parent.right; }
59 model: root.widgetData["reviews"]
61 delegate: PreviewRatingSingleDisplay {
63 objectName: "reviewItem" + index
65 anchors { left: parent.left; right: parent.right; }
67 rating: modelData["rating"] || -1
68 author: modelData["author"] || ""
69 review: modelData["review"] || ""
70 urlIconEmpty: widgetData["rating-icon-empty"]
71 urlIconFull: widgetData["rating-icon-full"]
72 urlIconHalf: widgetData["rating-icon-half"]
73 labelColor: scopeStyle ? scopeStyle.foreground : theme.palette.normal.baseText
76 onContentHeightChanged: ratingsList.updateRanges();
78 function updateRanges() {
79 var baseItem = root.parent;
80 if (!parentFlickable || !baseItem) {
81 ratingsList.displayMarginBeginning = 0;
82 ratingsList.displayMarginEnd = 0;
86 if (parentFlickable.moving) {
87 // Do not update the range if we are overshooting up or down, since we'll come back
88 // to the stable position and delete/create items without any reason
89 if (parentFlickable.contentY < parentFlickable.originY) {
91 } else if (parentFlickable.contentHeight - parentFlickable.originY > parentFlickable.height &&
92 parentFlickable.contentY + parentFlickable.height > parentFlickable.contentHeight) {
97 // A item view creates its delegates synchronously from
98 // -displayMarginBeginning
100 // height + displayMarginEnd
101 // Around that area it adds the cacheBuffer area where delegates are created async
103 // We adjust displayMarginEnd to be negative so that the range of created delegates matches
104 // from the beginning of the list to the end of the viewport.
105 // Ideally we would also use displayMarginBeginning
106 // so that delegates at the beginning get destroyed but that causes issues with
107 // listview and is not really necessary to provide the better experience we're after
108 var itemYOnViewPort = baseItem.y - parentFlickable.contentY;
109 var displayMarginEnd = -ratingsList.contentHeight + parentFlickable.height - itemYOnViewPort;
110 displayMarginEnd = -Math.max(-displayMarginEnd, 0);
111 displayMarginEnd = -Math.min(-displayMarginEnd, ratingsList.contentHeight);
112 displayMarginEnd = Math.round(displayMarginEnd);
114 ratingsList.displayMarginEnd = displayMarginEnd;