on 10cf7e2 help sign in
unity8/qml/Components/LazyImage.qml
200 lines 7.3 kB history raw
1/*
2 * Copyright (C) 2013-2016 Canonical, Ltd.
3 *
4 * Authors:
5 * Michał Sawicz <michal.sawicz@canonical.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
20import QtQuick 2.4
21import Ubuntu.Components 1.3
23Item {
24 id: root
26 property url source
27 // TODO convert into enums when available in QML
28 property string scaleTo
30 property real initialWidth: scaleTo == "width" || scaleTo == "fit" ? width : units.gu(10)
31 property real initialHeight: scaleTo == "height" || scaleTo == "fit" ? height : units.gu(10)
32 property real lastScaledDimension: scaleTo == "height" || scaleTo == "fit" ? width : height
34 property alias sourceSize: image.sourceSize
35 property alias asynchronous: image.asynchronous
36 property alias cache: image.cache
37 property alias sourceImage: image
39 property bool useUbuntuShape: true
40 property bool pressed: false
42 state: "default"
44 onSourceChanged: {
45 if (state === "ready") {
46 state = "default";
47 image.nextSource = source;
48 } else {
49 image.source = source;
50 }
51 }
53 Loader {
54 id: placeholder
55 objectName: "placeholder"
56 anchors.fill: shape
57 active: useUbuntuShape
58 visible: opacity != 0
59 sourceComponent: UbuntuShape {
60 backgroundColor: "#22FFFFFF"
61 }
63 ActivityIndicator {
64 id: activity
65 anchors.centerIn: parent
66 opacity: 0
67 visible: opacity != 0
69 running: visible
70 }
72 Image {
73 id: errorImage
74 objectName: "errorImage"
75 anchors.centerIn: parent
76 opacity: 0
77 visible: opacity != 0
79 source: "graphics/close.png"
80 sourceSize { width: units.gu(3); height: units.gu(3) }
81 }
82 }
84 Loader {
85 id: shape
86 objectName: "shape"
87 height: root.initialHeight
88 width: root.initialWidth
89 anchors.centerIn: root.scaleTo == "fit" ? parent : undefined
90 active: useUbuntuShape
91 opacity: 0
92 visible: opacity != 0
93 sourceComponent: UbuntuShapeOverlay {
94 property bool pressed: false
95 overlayColor: Qt.rgba(0, 0, 0, pressed ? 0.1 : 0)
96 overlayRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
97 }
98 onLoaded: {
99 item.source = image;
100 item.pressed = Qt.binding(function() { return root.pressed; });
101 }
103 Image {
104 id: image
105 objectName: "image"
107 property url nextSource
108 property string format: image.implicitWidth > image.implicitHeight ? "landscape" : "portrait"
110 anchors.fill: parent
111 visible: !useUbuntuShape
112 fillMode: Image.PreserveAspectFit
113 asynchronous: true
114 cache: false
115 sourceSize.width: root.scaleTo == "width" ? root.width
116 : root.scaleTo == "fit" && root.width <= root.height ? root.width
117 : 0
118 sourceSize.height: root.scaleTo == "height" ? root.height
119 : root.scaleTo == "fit" && root.height <= root.width ? root.height
120 : 0
121 }
122 }
124 states: [
125 State {
126 name: "default"
127 when: image.source == ""
128 PropertyChanges { target: root; implicitWidth: root.initialWidth; implicitHeight: root.initialHeight }
129 PropertyChanges { target: errorImage; opacity: 0 }
130 },
131 State {
132 name: "loading"
133 extend: "default"
134 when: image.status === Image.Loading
135 PropertyChanges { target: activity; opacity: 1 }
136 },
137 State {
138 name: "ready"
139 when: image.status === Image.Ready && image.source != ""
140 PropertyChanges { target: root; implicitWidth: shape.width; implicitHeight: shape.height }
141 PropertyChanges { target: placeholder; opacity: 0 }
142 PropertyChanges { target: shape; opacity: 1
143 width: root.scaleTo == "width" || (root.scaleTo == "fit" && image.format == "landscape") ? root.width
144 : root.scaleTo == "" ? image.implicitWidth : image.implicitWidth * height / image.implicitHeight
145 height: root.scaleTo == "height" || (root.scaleTo == "fit" && image.format == "portrait") ? root.height
146 : root.scaleTo == "" ? image.implicitHeight : image.implicitHeight * width / image.implicitWidth
147 }
148 },
149 State {
150 name: "error"
151 extend: "default"
152 when: image.status === Image.Error
153 PropertyChanges { target: errorImage; opacity: 1.0 }
154 }
155 ]
157 transitions: [
158 Transition {
159 to: "ready"
160 objectName: "readyTransition"
161 SequentialAnimation {
162 PropertyAction { target: shape; property: "visible" }
163 ParallelAnimation {
164 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
165 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
166 UbuntuNumberAnimation { target: shape; properties: "width,height" }
167 NumberAnimation {
168 targets: [placeholder, activity, errorImage]; property: "opacity";
169 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
170 }
171 }
172 ScriptAction { script: { lastScaledDimension = scaleTo == "height" || scaleTo == "fit" ? root.width : root.height } }
173 }
174 },
176 Transition {
177 to: "*"
178 objectName: "genericTransition"
179 SequentialAnimation {
180 ParallelAnimation {
181 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
182 NumberAnimation {
183 targets: [placeholder, activity, errorImage]; property: "opacity";
184 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
185 }
186 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
187 UbuntuNumberAnimation { target: shape; properties: "width,height" }
188 }
189 PropertyAction { target: shape; property: "visible" }
190 }
192 onRunningChanged: {
193 if (!running && state === "default" && image.nextSource !== "") {
194 image.source = image.nextSource;
195 image.nextSource = "";
196 }
197 }
198 }
199 ]