on a142f21 help sign in
unity8/qml/Components/LazyImage.qml
187 lines 6.8 kB history raw
1/*
2 * Copyright (C) 2013 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.0
21import Ubuntu.Components 0.1
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)
33 property alias sourceSize: image.sourceSize
34 property alias fillMode: image.fillMode
35 property alias asynchronous: image.asynchronous
36 property alias cache: image.cache
37 property alias horizontalAlignment: image.horizontalAlignment
38 property alias verticalAlignment: image.verticalAlignment
39 property alias sourceImage: image
40 property alias borderSource: shape.borderSource
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 UbuntuShape {
54 id: placeholder
55 objectName: "placeholder"
56 color: "#22FFFFFF"
57 anchors.fill: shape
58 visible: opacity != 0
60 ActivityIndicator {
61 id: activity
62 anchors.centerIn: parent
63 opacity: 0
64 visible: opacity != 0
66 running: visible
67 }
69 Image {
70 id: errorImage
71 objectName: "errorImage"
72 anchors.centerIn: parent
73 opacity: 0
74 visible: opacity != 0
76 source: "graphics/close.png"
77 sourceSize { width: units.gu(3); height: units.gu(3) }
78 }
79 }
81 UbuntuShape {
82 id: shape
83 objectName: "shape"
84 height: root.initialHeight
85 width: root.initialWidth
86 anchors.centerIn: root.scaleTo == "fit" ? parent : undefined
88 opacity: 0
89 visible: opacity != 0
91 image: Image {
92 id: image
93 objectName: "image"
95 property url nextSource
96 property string format: image.implicitWidth > image.implicitHeight ? "landscape" : "portrait"
98 fillMode: Image.PreserveAspectFit
99 asynchronous: true
100 cache: false
101 horizontalAlignment: Image.AlignHCenter
102 verticalAlignment: Image.AlignVCenter
103 sourceSize.width: root.scaleTo == "width" ? root.width
104 : root.scaleTo == "fit" && root.width <= root.height ? root.width
105 : 0
106 sourceSize.height: root.scaleTo == "height" ? root.height
107 : root.scaleTo == "fit" && root.height <= root.width ? root.height
108 : 0
109 }
110 }
112 states: [
113 State {
114 name: "default"
115 when: image.source == ""
116 PropertyChanges { target: root; implicitWidth: root.initialWidth; implicitHeight: root.initialHeight }
117 PropertyChanges { target: errorImage; opacity: 0 }
118 },
119 State {
120 name: "loading"
121 extend: "default"
122 when: image.status === Image.Loading
123 PropertyChanges { target: activity; opacity: 1 }
124 },
125 State {
126 name: "ready"
127 when: image.status === Image.Ready && image.source != ""
128 PropertyChanges { target: root; implicitWidth: shape.width; implicitHeight: shape.height }
129 PropertyChanges { target: placeholder; opacity: 0 }
130 PropertyChanges { target: shape; opacity: 1
131 width: root.scaleTo == "width" || (root.scaleTo == "fit" && image.format == "landscape") ? root.width
132 : root.scaleTo == "" ? image.implicitWidth : image.implicitWidth * height / image.implicitHeight
133 height: root.scaleTo == "height" || (root.scaleTo == "fit" && image.format == "portrait") ? root.height
134 : root.scaleTo == "" ? image.implicitHeight : image.implicitHeight * width / image.implicitWidth
135 }
136 },
137 State {
138 name: "error"
139 extend: "default"
140 when: image.status === Image.Error
141 PropertyChanges { target: errorImage; opacity: 1.0 }
142 }
143 ]
145 transitions: [
146 Transition {
147 to: "ready"
148 objectName: "readyTransition"
149 SequentialAnimation {
150 PropertyAction { target: shape; property: "visible" }
151 ParallelAnimation {
152 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
153 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
154 UbuntuNumberAnimation { target: shape; properties: "width,height" }
155 NumberAnimation {
156 targets: [placeholder, activity, errorImage]; property: "opacity";
157 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
158 }
159 }
160 }
161 },
163 Transition {
164 to: "*"
165 objectName: "genericTransition"
166 SequentialAnimation {
167 ParallelAnimation {
168 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
169 NumberAnimation {
170 targets: [placeholder, activity, errorImage]; property: "opacity";
171 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
172 }
173 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
174 UbuntuNumberAnimation { target: shape; properties: "width,height" }
175 }
176 PropertyAction { target: shape; property: "visible" }
177 }
179 onRunningChanged: {
180 if (!running && state === "default" && image.nextSource !== "") {
181 image.source = image.nextSource;
182 image.nextSource = "";
183 }
184 }
185 }
186 ]