@@ -25,47 +25,53 @@ AbstractButton {
2525 property var components
2626 property var cardData
2727
28− property alias fontScale: header.fontScale
29− property alias headerAlignment: header.headerAlignment
30− property alias headerHeight: header.height
31− readonly property alias title: header.title
28+ property real fontScale: 1.0
29+ property int headerAlignment: Text.AlignLeft
30+ readonly property int headerHeight: headerLoader.item ? headerLoader.item.height : 0
31+ property int fixedHeaderHeight: -1
32+ readonly property string title: cardData && cardData["title"] || ""
3233
3334 property bool showHeader: true
3435
3536 implicitWidth: childrenRect.width
36− implicitHeight: summary.y + summary.height + (summary.text && background.visible ? units.gu(1) : 0)
37+ implicitHeight: summary.y + summary.height + (summary.text && backgroundLoader.active ? units.gu(1) : 0)
3738
38− UbuntuShape {
39− id: background
40− objectName: "background"
41− radius: "medium"
42− visible: template["card-layout"] !== "horizontal" && (template["card-background"] || components["background"]
43− || artAndSummary)
44− property bool artAndSummary: components["art"]["field"] && components["summary"] || false
45− color: getColor(0) || "white"
46− gradientColor: getColor(1) || color
47− anchors.fill: parent
48− image: backgroundImage.source ? backgroundImage : null
39+ Loader {
40+ id: backgroundLoader
41+ objectName: "backgroundLoader"
4942
50− property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b
43+ readonly property bool artAndSummary: components["art"]["field"] && components["summary"] || false
44+ active: template["card-layout"] !== "horizontal" && (template["card-background"] || components["background"] || artAndSummary)
45+ anchors.fill: parent
5146
52− property Image backgroundImage: Image {
53− objectName: "backgroundImage"
54− source: {
55− if (cardData && typeof cardData["background"] === "string") return cardData["background"]
56− else if (template && typeof template["card-background"] === "string") return template["card-background"]
57− else return ""
47+ sourceComponent: UbuntuShape {
48+ objectName: "background"
49+ radius: "medium"
50+ color: getColor(0) || "white"
51+ gradientColor: getColor(1) || color
52+ anchors.fill: parent
53+ image: backgroundImage.source ? backgroundImage : null
54+
55+ property real luminance: 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b
56+
57+ property Image backgroundImage: Image {
58+ objectName: "backgroundImage"
59+ source: {
60+ if (cardData && typeof cardData["background"] === "string") return cardData["background"]
61+ else if (template && typeof template["card-background"] === "string") return template["card-background"]
62+ else return ""
63+ }
5864 }
59− }
6065
61− function getColor(index) {
62− if (cardData && typeof cardData["background"] === "object"
63− && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
64− return cardData["background"]["elements"][index];
65− } else if (template && typeof template["card-background"] === "object"
66− && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
67− return template["card-background"]["elements"][index];
68− } else return undefined;
66+ function getColor(index) {
67+ if (cardData && typeof cardData["background"] === "object"
68+ && (cardData["background"]["type"] === "color" || cardData["background"]["type"] === "gradient")) {
69+ return cardData["background"]["elements"][index];
70+ } else if (template && typeof template["card-background"] === "object"
71+ && (template["card-background"]["type"] === "color" || template["card-background"]["type"] === "gradient")) {
72+ return template["card-background"]["elements"][index];
73+ } else return undefined;
74+ }
6975 }
7076 }
7177
@@ -111,7 +117,7 @@ AbstractButton {
111117 function updateWidthHeightBindings() {
112118 if (isHorizontal) {
113119 width = Qt.binding(function() { return height * artShape.aspect });
114− height = Qt.binding(function() { return header.height });
120+ height = Qt.binding(function() { return root.headerHeight });
115121 } else {
116122 width = Qt.binding(function() { return root.width });
117123 height = Qt.binding(function() { return width / artShape.aspect });
@@ -120,53 +126,58 @@ AbstractButton {
120126 }
121127 }
122128
123− ShaderEffect {
124− id: overlay
129+ Loader {
130+ id: overlayLoader
125131 anchors {
126132 left: artShape.left
127133 right: artShape.right
128134 bottom: artShape.bottom
129135 }
136+ active: template && template["overlay"] && artShape.visible && artShape.image.status === Image.Ready || false
130137
131− height: header.height
132− opacity: header.opacity * 0.6
133− visible: template && template["overlay"] && artShape.visible && artShape.image.status === Image.Ready || false
138+ sourceComponent: ShaderEffect {
139+ id: overlay
134140
135− property var source: ShaderEffectSource {
136− id: shaderSource
137− sourceItem: artShape
138− onVisibleChanged: if (visible) scheduleUpdate()
139− live: false
140− sourceRect: Qt.rect(0, artShape.height - overlay.height, artShape.width, overlay.height)
141− }
141+ height: headerLoader.item ? headerLoader.item.height : 0
142+ opacity: headerLoader.item ? headerLoader.item.opacity * 0.6 : 0
143+
144+ property var source: ShaderEffectSource {
145+ id: shaderSource
146+ sourceItem: artShape
147+ onVisibleChanged: if (visible) scheduleUpdate()
148+ live: false
149+ sourceRect: Qt.rect(0, artShape.height - overlay.height, artShape.width, overlay.height)
150+ }
142151
143− vertexShader: "
144− uniform highp mat4 qt_Matrix;
145− attribute highp vec4 qt_Vertex;
146− attribute highp vec2 qt_MultiTexCoord0;
147− varying highp vec2 coord;
148− void main() {
149− coord = qt_MultiTexCoord0;
150− gl_Position = qt_Matrix * qt_Vertex;
151− }"
152−
153− fragmentShader: "
154− varying highp vec2 coord;
155− uniform sampler2D source;
156− uniform lowp float qt_Opacity;
157− void main() {
158− lowp vec4 tex = texture2D(source, coord);
159− gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
160− }"
152+ vertexShader: "
153+ uniform highp mat4 qt_Matrix;
154+ attribute highp vec4 qt_Vertex;
155+ attribute highp vec2 qt_MultiTexCoord0;
156+ varying highp vec2 coord;
157+ void main() {
158+ coord = qt_MultiTexCoord0;
159+ gl_Position = qt_Matrix * qt_Vertex;
160+ }"
161+
162+ fragmentShader: "
163+ varying highp vec2 coord;
164+ uniform sampler2D source;
165+ uniform lowp float qt_Opacity;
166+ void main() {
167+ lowp vec4 tex = texture2D(source, coord);
168+ gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
169+ }"
170+ }
161171 }
162172
163− CardHeader {
164− id: header
165− objectName: "cardHeader"
173+ Loader {
174+ id: headerLoader
175+ objectName: "cardHeaderLoader"
176+
166177 anchors {
167178 top: {
168179 if (template) {
169− if (template["overlay"]) return overlay.top;
180+ if (template["overlay"]) return overlayLoader.top;
170181 if (template["card-layout"] === "horizontal") return artShape.top;
171182 }
172183 return artShape.bottom;
@@ -179,29 +190,38 @@ AbstractButton {
179190 }
180191 right: parent.right
181192 }
193+ active: cardData && cardData["title"] || cardData && cardData["mascot"] || false
194+
195+ sourceComponent: CardHeader {
196+ id: header
197+ objectName: "cardHeader"
182198
183− mascot: cardData && cardData["mascot"] || ""
184− title: cardData && cardData["title"] || ""
185− subtitle: cardData && cardData["subtitle"] || ""
199+ mascot: cardData && cardData["mascot"] || ""
200+ title: root.title
201+ subtitle: cardData && cardData["subtitle"] || ""
186202
187− titleWeight: components && components["subtitle"] ? Font.DemiBold : Font.Normal
203+ titleWeight: components && components["subtitle"] ? Font.DemiBold : Font.Normal
188204
189− opacity: showHeader ? 1 : 0
190− inOverlay: root.template && root.template["overlay"] === true
191− fontColor: inOverlay ? "white" : summary.color
192− useMascotShape: !background.visible && !inOverlay
205+ opacity: showHeader ? 1 : 0
206+ inOverlay: root.template && root.template["overlay"] === true
207+ fontColor: inOverlay ? "white" : summary.color
208+ useMascotShape: !backgroundLoader.active && !inOverlay
209+ headerAlignment: root.headerAlignment
210+ height: root.fixedHeaderHeight != -1 ? root.fixedHeaderHeight : implicitHeight
211+ fontScale: root.fontScale
193212
194− Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
213+ Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
214+ }
195215 }
196216
197217 Label {
198218 id: summary
199219 objectName: "summaryLabel"
200220 anchors {
201− top: header.visible ? header.bottom : artShape.bottom
221+ top: headerLoader.active ? headerLoader.bottom : artShape.bottom
202222 left: parent.left
203223 right: parent.right
204− margins: background.visible ? units.gu(1) : 0
224+ margins: backgroundLoader.active ? units.gu(1) : 0
205225 topMargin: 0
206226 }
207227 wrapMode: Text.Wrap
@@ -211,6 +231,6 @@ AbstractButton {
211231 height: text ? implicitHeight : 0
212232 fontSize: "small"
213233 // TODO karni: Change "grey" to Ubuntu.Components.Palette color once updated.
214− color: background.visible && background.luminance < 0.7 ? "white" : "grey"
234+ color: backgroundLoader.active && backgroundLoader.item.luminance < 0.7 ? "white" : "grey"
215235 }
216236}