on xenial help sign in
adds "fit" mode to LazyImage.
e77c275Michael Zanetti
Components/LazyImage.qml+28−9
@@ -52,7 +52,9 @@ Item {
52 id: placeholder
52 id: placeholder
53 objectName: "placeholder"
53 objectName: "placeholder"
54 color: "#22FFFFFF"
54 color: "#22FFFFFF"
55− anchors.fill: parent
55+ width: shape.width
56+ height: shape.height
57+ anchors.centerIn: shape
56 visible: opacity != 0
58 visible: opacity != 0
57
59
58 ActivityIndicator {
60 ActivityIndicator {
@@ -79,7 +81,11 @@ Item {
79 UbuntuShape {
81 UbuntuShape {
80 id: shape
82 id: shape
81 objectName: "shape"
83 objectName: "shape"
84+ // w : h = i.w : i.h
85+ height: root.initialHeight
86+ width: root.initialWidth
87+
82− anchors.fill: parent
88+ anchors.centerIn: root.scaleTo == "fit" ? parent : undefined
83 opacity: 0
89 opacity: 0
84 visible: opacity != 0
90 visible: opacity != 0
85
91
@@ -88,16 +94,19 @@ Item {
88 objectName: "image"
94 objectName: "image"
89
95
90 property url nextSource
96 property url nextSource
97+ property string format: image.implicitWidth > image.implicitHeight ? "landscape" : "portrait"
91
98
92− width: root.scaleTo == "height" ? implicitWidth * root.height / implicitHeight : implicitWidth
93− height: root.scaleTo == "width" ? implicitHeight * root.width / implicitWidth : implicitHeight
94− fillMode: Image.PreserveAspectCrop
99+ fillMode: Image.PreserveAspectFit
95 asynchronous: true
100 asynchronous: true
96 cache: false
101 cache: false
97 horizontalAlignment: Image.AlignHCenter
102 horizontalAlignment: Image.AlignHCenter
98 verticalAlignment: Image.AlignVCenter
103 verticalAlignment: Image.AlignVCenter
99− sourceSize.width: root.scaleTo == "width" ? root.width : 0
104+ sourceSize.width: root.scaleTo == "width" ? root.width
105+ : root.scaleTo == "fit" && root.width < root.height ? root.width
106+ : undefined
100− sourceSize.height: root.scaleTo == "height" ? root.height : 0
107+ sourceSize.height: root.scaleTo == "height" ? root.height
108+ : root.scale == "fit" && root.height < root.width ? root.height
109+ : undefined
101 }
110 }
102 }
111 }
103
112
@@ -107,6 +116,7 @@ Item {
107 when: image.source == ""
116 when: image.source == ""
108 PropertyChanges { target: root; implicitWidth: root.initialWidth; implicitHeight: root.initialHeight }
117 PropertyChanges { target: root; implicitWidth: root.initialWidth; implicitHeight: root.initialHeight }
109 PropertyChanges { target: errorImage; opacity: 0 }
118 PropertyChanges { target: errorImage; opacity: 0 }
119+ PropertyChanges { target: placeholder; width: root.initialWidth; height: root.initialHeight }
110 },
120 },
111 State {
121 State {
112 name: "loading"
122 name: "loading"
@@ -117,9 +127,14 @@ Item {
117 State {
127 State {
118 name: "ready"
128 name: "ready"
119 when: image.status === Image.Ready && image.source != ""
129 when: image.status === Image.Ready && image.source != ""
120− PropertyChanges { target: root; implicitWidth: image.width; implicitHeight: image.height }
130+ PropertyChanges { target: root; implicitWidth: shape.width; implicitHeight: shape.height }
121− PropertyChanges { target: shape; opacity: 1 }
122 PropertyChanges { target: placeholder; opacity: 0 }
131 PropertyChanges { target: placeholder; opacity: 0 }
132+ PropertyChanges { target: shape; opacity: 1
133+ width: root.scaleTo == "width" || (root.scaleTo == "fit" && image.format == "landscape") ? root.width
134+ : root.scaleTo == "" ? image.implicitWidth : image.implicitWidth * height / image.implicitHeight
135+ height: root.scaleTo == "height" || (root.scaleTo == "fit" && image.format == "portrait") ? root.height
136+ : root.scaleTo == "" ? image.implicitHeight : image.implicitHeight * width / image.implicitWidth
137+ }
123 },
138 },
124 State {
139 State {
125 name: "error"
140 name: "error"
@@ -138,6 +153,8 @@ Item {
138 ParallelAnimation {
153 ParallelAnimation {
139 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
154 NumberAnimation { target: shape; property: "opacity"; easing.type: Easing.Linear }
140 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
155 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
156+ UbuntuNumberAnimation { target: shape; properties: "width,height" }
157+ UbuntuNumberAnimation { target: placeholder; properties: "width,height" }
141 NumberAnimation {
158 NumberAnimation {
142 targets: [placeholder, activity, errorImage]; property: "opacity";
159 targets: [placeholder, activity, errorImage]; property: "opacity";
143 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
160 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
@@ -157,6 +174,8 @@ Item {
157 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
174 easing.type: Easing.Linear; duration: UbuntuAnimation.SnapDuration
158 }
175 }
159 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
176 UbuntuNumberAnimation { target: root; properties: "implicitWidth,implicitHeight" }
177+ UbuntuNumberAnimation { target: shape; properties: "width,height" }
178+ UbuntuNumberAnimation { target: placeholder; properties: "width,height" }
160 }
179 }
161 PropertyAction { target: shape; property: "visible" }
180 PropertyAction { target: shape; property: "visible" }
162 }
181 }
tests/qmltests/Components/tst_LazyImage.qml+40−15
@@ -73,6 +73,20 @@ Rectangle {
73 height: units.gu(10)
73 height: units.gu(10)
74 scaleTo: "height"
74 scaleTo: "height"
75 }
75 }
76+
77+ Label {
78+ height: units.gu(4)
79+ text: "Fit"
80+ color: "white"
81+ verticalAlignment: Text.AlignBottom
82+ }
83+
84+ LazyImage {
85+ id: lazy4
86+ height: units.gu(10)
87+ width: units.gu(10)
88+ scaleTo: "fit"
89+ }
76 }
90 }
77 }
91 }
78
92
@@ -94,6 +108,7 @@ Rectangle {
94 ImageControls { id: controls1; image: lazy1 }
108 ImageControls { id: controls1; image: lazy1 }
95 ImageControls { id: controls2; image: lazy2 }
109 ImageControls { id: controls2; image: lazy2 }
96 ImageControls { id: controls3; image: lazy3 }
110 ImageControls { id: controls3; image: lazy3 }
111+ ImageControls { id: controls4; image: lazy4 }
97 }
112 }
98 }
113 }
99
114
@@ -112,21 +127,26 @@ Rectangle {
112
127
113 function test_lazyimage_data() {
128 function test_lazyimage_data() {
114 return [
129 return [
115− {tag: "Unbound Blank", image: lazy1, func: controls1.blank, width: units.gu(10), height: units.gu(10), placeholder: true},
130+ {tag: "Unbound Blank", image: lazy1, func: controls1.blank, width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true},
116− {tag: "Unbound Wide", image: lazy1, func: controls1.wide, transition: "readyTransition", width: 160, height: 80},
131+ {tag: "Unbound Wide", image: lazy1, func: controls1.wide, transition: "readyTransition", width: 160, height: 80, imageWidth: 160, imageHeight: 80},
117− {tag: "Unbound Square", image: lazy1, func: controls1.square, transition: "readyTransition", width: 160, height: 160},
132+ {tag: "Unbound Square", image: lazy1, func: controls1.square, transition: "readyTransition", width: 160, height: 160, imageWidth: 160, imageHeight: 160},
118− {tag: "Unbound Portrait", image: lazy1, func: controls1.portrait, transition: "readyTransition", width: 80, height: 160},
133+ {tag: "Unbound Portrait", image: lazy1, func: controls1.portrait, transition: "readyTransition", width: 80, height: 160, imageWidth: 80, imageHeight: 160},
119− {tag: "Unbound Bad path", image: lazy1, func: controls1.badpath, transition: "genericTransition", width: units.gu(10), height: units.gu(10), placeholder: true, error: true},
134+ {tag: "Unbound Bad path", image: lazy1, func: controls1.badpath, transition: "genericTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true, error: true},
120− {tag: "Width-bound Blank", image: lazy2, func: controls2.blank, width: units.gu(30), height: units.gu(10), placeholder: true},
135+ {tag: "Width-bound Blank", image: lazy2, func: controls2.blank, width: units.gu(30), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true},
121− {tag: "Width-bound Wide", image: lazy2, func: controls2.wide, transition: "readyTransition", width: units.gu(30), height: units.gu(15)},
136+ {tag: "Width-bound Wide", image: lazy2, func: controls2.wide, transition: "readyTransition", width: units.gu(30), height: units.gu(15), imageWidth: units.gu(30), imageHeight: units.gu(15)},
122− {tag: "Width-bound Square", image: lazy2, func: controls2.square, transition: "readyTransition", width: units.gu(30), height: units.gu(30)},
137+ {tag: "Width-bound Square", image: lazy2, func: controls2.square, transition: "readyTransition", width: units.gu(30), height: units.gu(30), imageWidth: units.gu(30), imageHeight: units.gu(30)},
123− {tag: "Width-bound Portrait", image: lazy2, func: controls2.portrait, transition: "readyTransition", width: units.gu(30), height: units.gu(60)},
138+ {tag: "Width-bound Portrait", image: lazy2, func: controls2.portrait, transition: "readyTransition", width: units.gu(30), height: units.gu(60), imageWidth: units.gu(30), imageHeight: units.gu(60)},
124− {tag: "Width-bound Bad path", image: lazy2, func: controls2.badpath, transition: "genericTransition", width: units.gu(30), height: units.gu(10), placeholder: true, error: true},
139+ {tag: "Width-bound Bad path", image: lazy2, func: controls2.badpath, transition: "genericTransition", width: units.gu(30), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true, error: true},
125− {tag: "Height-bound Blank", image: lazy3, func: controls3.blank, width: units.gu(10), height: units.gu(10), placeholder: true},
140+ {tag: "Height-bound Blank", image: lazy3, func: controls3.blank, width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true},
126− {tag: "Height-bound Wide", image: lazy3, func: controls3.wide, transition: "readyTransition", width: units.gu(20), height: units.gu(10)},
141+ {tag: "Height-bound Wide", image: lazy3, func: controls3.wide, transition: "readyTransition", width: units.gu(20), height: units.gu(10), imageWidth: units.gu(20), imageHeight: units.gu(10)},
127− {tag: "Height-bound Square", image: lazy3, func: controls3.square, transition: "readyTransition", width: units.gu(10), height: units.gu(10)},
142+ {tag: "Height-bound Square", image: lazy3, func: controls3.square, transition: "readyTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10)},
128− {tag: "Height-bound Portrait", image: lazy3, func: controls3.portrait, transition: "readyTransition", width: units.gu(5), height: units.gu(10)},
143+ {tag: "Height-bound Portrait", image: lazy3, func: controls3.portrait, transition: "readyTransition", width: units.gu(5), height: units.gu(10), imageWidth: units.gu(5), imageHeight: units.gu(10)},
129− {tag: "Height-bound Bad path", image: lazy3, func: controls3.badpath, transition: "genericTransition", width: units.gu(10), height: units.gu(10), placeholder: true, error: true},
144+ {tag: "Height-bound Bad path", image: lazy3, func: controls3.badpath, transition: "genericTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true, error: true},
145+ {tag: "Fit Blank", image: lazy4, func: controls4.blank, width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true},
146+ {tag: "Fit Wide", image: lazy4, func: controls4.wide, transition: "readyTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(5)},
147+ {tag: "Fit Square", image: lazy4, func: controls4.square, transition: "readyTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10)},
148+ {tag: "Fit Portrait", image: lazy4, func: controls4.portrait, transition: "readyTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(5), imageHeight: units.gu(10)},
149+ {tag: "Fit Bad path", image: lazy4, func: controls4.badpath, transition: "genericTransition", width: units.gu(10), height: units.gu(10), imageWidth: units.gu(10), imageHeight: units.gu(10), placeholder: true, error: true},
130 ]
150 ]
131 }
151 }
132
152
@@ -144,6 +164,11 @@ Rectangle {
144 compare(data.image.width, data.width);
164 compare(data.image.width, data.width);
145 compare(data.image.height, data.height);
165 compare(data.image.height, data.height);
146
166
167+ // check the shape dimensions
168+ var shape = findChild(data.image, "shape");
169+ compare(shape.width, data.imageWidth);
170+ compare(shape.height, data.imageHeight);
171+
147 // check the placeholder
172 // check the placeholder
148 var placeholder = findChild(data.image, "placeholder");
173 var placeholder = findChild(data.image, "placeholder");
149 compare(placeholder.visible, data.placeholder ? true : false);
174 compare(placeholder.visible, data.placeholder ? true : false);