@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013, 2015 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -36,44 +36,40 @@ StyledItem {
3636 property var type
3737 property var hints
3838 property var notification
39− property color color
39+ property color color: theme.palette.normal.background
4040 property bool fullscreen: false
4141 property int maxHeight
42− property int margins
43− readonly property bool draggable: (type === Notification.SnapDecision && state === "contracted") || type === Notification.Interactive || type === Notification.Ephemeral
44− readonly property bool darkOnBright: inverseMode || type === Notification.SnapDecision
45− readonly property color sdLightGrey: "#eaeaea"
46− readonly property real contentSpacing: units.gu(2)
47− readonly property bool canBeClosed: type === Notification.Ephemeral
42+ property int margins: units.gu(1)
43+
44+ readonly property real defaultOpacity: 1.0
4845 property bool hasMouse
49− property bool inverseMode
5046 property url background: ""
5147
5248 objectName: "background"
53− implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : outterColumn.height - shapedBack.anchors.topMargin + contentSpacing * 2) : 0
49+ implicitHeight: type !== Notification.PlaceHolder ? (fullscreen ? maxHeight : outterColumn.height + shapedBack.anchors.topMargin + margins * 2) : 0
5450
55− color: (type === Notification.Confirmation && notificationList.useModal && !greeter.shown) || darkOnBright ? sdLightGrey : Qt.rgba(0.132, 0.117, 0.109, 0.97)
56− opacity: 1 - (x / notification.width) // FIXME: non-zero initially because of LP: #1354406 workaround, we want this to start at 0 upon creation eventually
51+ // FIXME: non-zero initially because of LP: #1354406 workaround, we want this to start at 0 upon creation eventually
52+ opacity: defaultOpacity - Math.abs(x / notification.width)
5753
5854 theme: ThemeSettings {
59− name: darkOnBright ? "Ubuntu.Components.Themes.Ambiance" : "Ubuntu.Components.Themes.SuruDark"
55+ name: "Ubuntu.Components.Themes.Ambiance"
6056 }
6157
62− state: {
63− var result = "";
58+ readonly property bool expanded: {
59+ var result = false;
6460
65− if (type == Notification.SnapDecision) {
66− if (ListView.view.currentIndex == index) {
67− result = "expanded";
61+ if (type === Notification.SnapDecision) {
62+ if (ListView.view.currentIndex === index) {
63+ result = true;
6864 } else {
6965 if (ListView.view.count > 2) {
70− if (ListView.view.currentIndex == -1 && index == 1) {
71− result = "expanded";
66+ if (ListView.view.currentIndex === -1 && index == 1) {
67+ result = true;
7268 } else {
73− result = "contracted";
69+ result = false;
7470 }
7571 } else {
76− result = "expanded";
72+ result = true;
7773 }
7874 }
7975 }
@@ -90,72 +86,66 @@ StyledItem {
9086 Component.onCompleted: {
9187 // Turn on screen as needed (Powerd.Notification means the screen
9288 // stays on for a shorter amount of time)
93− if (type == Notification.SnapDecision) {
89+ if (type === Notification.SnapDecision) {
9490 Powerd.setStatus(Powerd.On, Powerd.SnapDecision);
95− } else if (type != Notification.Confirmation) {
91+ } else if (type !== Notification.Confirmation) {
9692 Powerd.setStatus(Powerd.On, Powerd.Notification);
9793 }
9894
9995 // FIXME: using onCompleted because of LP: #1354406 workaround, has to be onOpacityChanged really
100− if (opacity == 1.0 && hints["suppress-sound"] !== "true" && sound.source !== "") {
96+ if (opacity == defaultOpacity && hints["suppress-sound"] !== "true" && sound.source !== "") {
10197 sound.play();
10298 }
10399 }
104100
105− Behavior on x {
106− id: normalXBehavior
107−
108− enabled: draggable
109− UbuntuNumberAnimation {
110− duration: UbuntuAnimation.FastDuration
111− easing.type: Easing.OutBounce
101+ function closeNotification() {
102+ if (notification.actions.count > 1) { // perform the "reject" action
103+ notification.notification.invokeAction(notification.actions.data(1, ActionModel.RoleActionId));
112104 }
105+ notification.notification.close();
106+ }
107+
108+ Behavior on x {
109+ UbuntuNumberAnimation { easing.type: Easing.OutBounce }
113110 }
114111
115112 onHintsChanged: {
116− if (type === Notification.Confirmation && opacity == 1.0 && hints["suppress-sound"] !== "true" && sound.source !== "") {
113+ if (type === Notification.Confirmation && opacity == defaultOpacity && hints["suppress-sound"] !== "true" && sound.source !== "") {
117114 sound.play();
118115 }
119116 }
120117
121118 Behavior on height {
122− id: normalHeightBehavior
123−
124− //enabled: menuItemFactory.progress == 1
125− enabled: true
126119 UbuntuNumberAnimation {
127120 duration: UbuntuAnimation.SnapDuration
128121 }
129122 }
130123
131− states:[
132− State {
133− name: "contracted"
134− PropertyChanges {target: notification; height: units.gu(10)}
135− },
136− State {
137− name: "expanded"
138− PropertyChanges {target: notification; height: implicitHeight}
139− }
140− ]
141−
142− clip: fullscreen ? false : true
124+ visible: type !== Notification.PlaceHolder
143125
144− visible: type != Notification.PlaceHolder
126+ BorderImage {
127+ anchors {
128+ fill: contents
129+ margins: shapedBack.visible ? -units.gu(1) : -units.gu(1.5)
130+ }
131+ source: "../Stages/graphics/dropshadow2gu.sci"
132+ opacity: notification.opacity * 0.5
133+ enabled: !fullscreen
134+ }
145135
146136 UbuntuShape {
147137 id: shapedBack
138+ objectName: "shapedBack"
148139
149140 visible: !fullscreen
150141 anchors {
151142 fill: parent
152143 leftMargin: notification.margins
153144 rightMargin: notification.margins
154− topMargin: type === Notification.Confirmation ? units.gu(.5) : 0
145+ topMargin: index == 0 ? notification.margins : 0
155146 }
156147 backgroundColor: parent.color
157− opacity: parent.opacity
158− radius: "medium"
148+ radius: "small"
159149 aspect: UbuntuShape.Flat
160150 }
161151
@@ -165,12 +155,11 @@ StyledItem {
165155 visible: fullscreen
166156 anchors.fill: parent
167157 color: parent.color
168− opacity: parent.opacity
169158 }
170159
171160 onXChanged: {
172− if (draggable && notification.x > 0.75 * notification.width) {
173− notification.notification.close()
161+ if (Math.abs(notification.x) > 0.75 * notification.width) {
162+ closeNotification();
174163 }
175164 }
176165
@@ -210,22 +199,21 @@ StyledItem {
210199 anchors.fill: parent
211200 objectName: "interactiveArea"
212201
213− drag.target: draggable ? notification : undefined
202+ drag.target: notification
214203 drag.axis: Drag.XAxis
215− drag.minimumX: 0
204+ drag.minimumX: -notification.width
216205 drag.maximumX: notification.width
206+ hoverEnabled: true
217207
218208 onClicked: {
219− if (notification.type == Notification.Interactive) {
209+ if (notification.type === Notification.Interactive) {
220210 notification.notification.invokeAction(actionRepeater.itemAt(0).actionId)
221− } else if (hasMouse && canBeClosed) {
222− notification.notification.close()
223211 } else {
224212 notificationList.currentIndex = index;
225213 }
226214 }
227215 onReleased: {
228− if (notification.x < notification.width / 2) {
216+ if (Math.abs(notification.x) < notification.width / 2) {
229217 notification.x = 0
230218 } else {
231219 notification.x = notification.width
@@ -233,44 +221,61 @@ StyledItem {
233221 }
234222 }
235223
224+ NotificationButton {
225+ objectName: "closeButton"
226+ width: units.gu(2)
227+ height: width
228+ radius: width / 2
229+ visible: hasMouse && (containsMouse || interactiveArea.containsMouse)
230+ iconName: "close"
231+ outline: false
232+ hoverEnabled: true
233+ color: theme.palette.normal.negative
234+ anchors.horizontalCenter: parent.left
235+ anchors.horizontalCenterOffset: notification.parent.state === "narrow" ? notification.margins / 2 : 0
236+ anchors.verticalCenter: parent.top
237+ anchors.verticalCenterOffset: notification.parent.state === "narrow" ? notification.margins / 2 : 0
238+
239+ onClicked: closeNotification();
240+ }
241+
236242 Column {
237243 id: outterColumn
244+ objectName: "outterColumn"
238245
239246 anchors {
240247 left: parent.left
241248 right: parent.right
242249 top: parent.top
243− margins: 0
244− topMargin: fullscreen ? 0 : type === Notification.Confirmation ? units.gu(1) : units.gu(2)
250+ margins: !fullscreen ? notification.margins : 0
245251 }
246252
247− spacing: type === Notification.Confirmation ? units.gu(1) : units.gu(2)
253+ spacing: notification.margins
248254
249255 Row {
250256 id: topRow
251257
252− spacing: contentSpacing
258+ spacing: notification.margins
253259 anchors {
254260 left: parent.left
255261 right: parent.right
256− margins: contentSpacing
257262 }
258263
259264 ShapedIcon {
260265 id: icon
261266
262267 objectName: "icon"
263− width: type == Notification.Ephemeral && !bodyLabel.visible ? units.gu(3) : units.gu(6)
268+ width: units.gu(6)
264269 height: width
265− shaped: notification.hints["x-canonical-non-shaped-icon"] == "true" ? false : true
266− visible: iconSource !== undefined && iconSource !== "" && type !== Notification.Confirmation
270+ shaped: notification.hints["x-canonical-non-shaped-icon"] !== "true"
271+ visible: iconSource !== "" && type !== Notification.Confirmation
267272 }
268273
269274 Column {
270275 id: labelColumn
271− width: secondaryIcon.visible ? parent.width - x - units.gu(4.5) : parent.width - x
272−
276+ width: secondaryIcon.visible ? parent.width - x - units.gu(3) : parent.width - x
273277 anchors.verticalCenter: (icon.visible && !bodyLabel.visible) ? icon.verticalCenter : undefined
278+ spacing: units.gu(.4)
274279
275280 Label {
276281 id: summaryLabel
@@ -282,6 +287,8 @@ StyledItem {
282287 }
283288 visible: type !== Notification.Confirmation
284289 fontSize: "medium"
290+ font.weight: Font.Light
291+ color: theme.palette.normal.backgroundSecondaryText
285292 elide: Text.ElideRight
286293 textFormat: Text.PlainText
287294 }
@@ -296,10 +303,13 @@ StyledItem {
296303 }
297304 visible: body != "" && type !== Notification.Confirmation
298305 fontSize: "small"
306+ font.weight: Font.Light
307+ color: theme.palette.normal.backgroundTertiaryText
299308 wrapMode: Text.Wrap
300− maximumLineCount: type == Notification.SnapDecision ? 12 : 2
309+ maximumLineCount: type === Notification.SnapDecision ? 12 : 2
301310 elide: Text.ElideRight
302311 textFormat: Text.PlainText
312+ lineHeight: 1.1
303313 }
304314 }
305315
@@ -307,25 +317,34 @@ StyledItem {
307317 id: secondaryIcon
308318
309319 objectName: "secondaryIcon"
310− width: units.gu(3)
311− height: units.gu(3)
320+ width: units.gu(2)
321+ height: width
312322 visible: status === Image.Ready
313323 fillMode: Image.PreserveAspectCrop
314324 }
315325 }
316326
317327 ListItem.ThinDivider {
318− visible: type == Notification.SnapDecision
328+ visible: type === Notification.SnapDecision && notification.expanded
329+ }
330+
331+ Icon {
332+ name: "toolkit_chevron-down_3gu"
333+ visible: type === Notification.SnapDecision && !notification.expanded
334+ width: units.gu(2)
335+ height: width
336+ anchors.horizontalCenter: parent.horizontalCenter
337+ color: theme.palette.normal.base
319338 }
320339
321340 ShapedIcon {
322341 id: centeredIcon
323342 objectName: "centeredIcon"
324− width: units.gu(5)
343+ width: units.gu(4)
325344 height: width
326− shaped: notification.hints["x-canonical-non-shaped-icon"] == "true" ? false : true
345+ shaped: notification.hints["x-canonical-non-shaped-icon"] !== "true"
327346 fileSource: icon.fileSource
328− visible: fileSource !== undefined && fileSource !== "" && type === Notification.Confirmation
347+ visible: fileSource !== "" && type === Notification.Confirmation
329348 anchors.horizontalCenter: parent.horizontalCenter
330349 }
331350
@@ -336,44 +355,32 @@ StyledItem {
336355 anchors.horizontalCenter: parent.horizontalCenter
337356 visible: type === Notification.Confirmation && body !== ""
338357 fontSize: "medium"
358+ font.weight: Font.Light
359+ color: theme.palette.normal.backgroundSecondaryText
339360 wrapMode: Text.WordWrap
340361 maximumLineCount: 1
341362 elide: Text.ElideRight
342363 textFormat: Text.PlainText
343364 }
344365
345− UbuntuShape {
366+ ProgressBar {
346367 id: valueIndicator
347368 objectName: "valueIndicator"
348369 visible: type === Notification.Confirmation
349− property double value
350−
370+ minimumValue: 0
371+ maximumValue: 100
372+ showProgressPercentage: false
351373 anchors {
352374 left: parent.left
353375 right: parent.right
354− margins: contentSpacing
355376 }
356−
357377 height: units.gu(1)
358− backgroundColor: theme.palette.normal.background
359− aspect: UbuntuShape.Flat
360− radius: "small"
361−
362− UbuntuShape {
363− id: innerBar
364− objectName: "innerBar"
365− width: valueIndicator.width * valueIndicator.value / 100
366− height: units.gu(1)
367− backgroundColor: notification.hints["x-canonical-value-bar-tint"] === "true" ? theme.palette.normal.activity : theme.palette.highlighted.foreground
368− aspect: UbuntuShape.Flat
369− radius: "small"
370− }
371378 }
372379
373380 Column {
374381 id: dialogColumn
375382 objectName: "dialogListView"
376− spacing: units.gu(2)
383+ spacing: notification.margins
377384
378385 visible: count > 0
379386
@@ -417,12 +424,11 @@ StyledItem {
417424 anchors {
418425 left: parent.left
419426 right: parent.right
420− margins: contentSpacing
421427 }
422428
423− spacing: contentSpacing
429+ spacing: notification.margins
424430
425− visible: notification.type === Notification.SnapDecision && oneOverTwoRepeaterTop.count === 3
431+ visible: notification.type === Notification.SnapDecision && oneOverTwoRepeaterTop.count === 3 && notification.expanded
426432
427433 Repeater {
428434 id: oneOverTwoRepeaterTop
@@ -437,11 +443,13 @@ StyledItem {
437443 Component {
438444 id: oneOverTwoButtonTop
439445
440− Button {
446+ NotificationButton {
441447 objectName: "notify_oot_button" + index
442448 width: oneOverTwoCase.width
443449 text: oneOverTwoLoaderTop.actionLabel
444− color: notification.hints["x-canonical-private-affirmative-tint"] == "true" ? UbuntuColors.green : theme.palette.normal.baseText
450+ outline: notification.hints["x-canonical-private-affirmative-tint"] !== "true"
451+ color: notification.hints["x-canonical-private-affirmative-tint"] === "true" ? theme.palette.normal.positive
452+ : theme.palette.normal.foreground
445453 onClicked: notification.notification.invokeAction(oneOverTwoLoaderTop.actionId)
446454 }
447455 }
@@ -450,7 +458,7 @@ StyledItem {
450458 }
451459
452460 Row {
453− spacing: contentSpacing
461+ spacing: notification.margins
454462
455463 Repeater {
456464 id: oneOverTwoRepeaterBottom
@@ -465,11 +473,13 @@ StyledItem {
465473 Component {
466474 id: oneOverTwoButtonBottom
467475
468− Button {
476+ NotificationButton {
469477 objectName: "notify_oot_button" + index
470− width: oneOverTwoCase.width / 2 - spacing * 2
478+ width: oneOverTwoCase.width / 2 - spacing / 2
471479 text: oneOverTwoLoaderBottom.actionLabel
472− color: index == 1 && notification.hints["x-canonical-private-rejection-tint"] == "true" ? UbuntuColors.red : theme.palette.normal.baseText
480+ outline: notification.hints["x-canonical-private-rejection-tint"] !== "true"
481+ color: index == 1 && notification.hints["x-canonical-private-rejection-tint"] === "true" ? theme.palette.normal.negative
482+ : theme.palette.normal.foreground
473483 onClicked: notification.notification.invokeAction(oneOverTwoLoaderBottom.actionId)
474484 }
475485 }
@@ -486,10 +496,9 @@ StyledItem {
486496 anchors {
487497 left: parent.left
488498 right: parent.right
489− margins: contentSpacing
490499 }
491− visible: notification.type === Notification.SnapDecision && actionRepeater.count > 0 && !oneOverTwoCase.visible
492− spacing: contentSpacing
500+ visible: notification.type === Notification.SnapDecision && actionRepeater.count > 0 && !oneOverTwoCase.visible && notification.expanded
501+ spacing: notification.margins
493502 layoutDirection: Qt.RightToLeft
494503
495504 Loader {
@@ -525,17 +534,19 @@ StyledItem {
525534 Component {
526535 id: actionButton
527536
528− Button {
537+ NotificationButton {
529538 objectName: "notify_button" + index
530− width: buttonRow.width / 2 - spacing * 2
539+ width: buttonRow.width / 2 - spacing / 2
531540 text: loader.actionLabel
541+ outline: (index == 0 && notification.hints["x-canonical-private-affirmative-tint"] !== "true") ||
542+ (index == 1 && notification.hints["x-canonical-private-rejection-tint"] !== "true")
532543 color: {
533− var result = theme.palette.normal.baseText;
534− if (index == 0 && notification.hints["x-canonical-private-affirmative-tint"] == "true") {
535− result = UbuntuColors.green;
544+ var result = theme.palette.normal.foreground;
545+ if (index == 0 && notification.hints["x-canonical-private-affirmative-tint"] === "true") {
546+ result = theme.palette.normal.positive;
536547 }
537− if (index == 1 && notification.hints["x-canonical-private-rejection-tint"] == "true") {
538− result = UbuntuColors.red;
548+ if (index == 1 && notification.hints["x-canonical-private-rejection-tint"] === "true") {
549+ result = theme.palette.normal.negative;
539550 }
540551 return result;
541552 }
@@ -554,10 +565,9 @@ StyledItem {
554565 anchors {
555566 left: parent.left
556567 right: parent.right
557− margins: contentSpacing
558568 }
559569
560− visible: notification.type == Notification.SnapDecision && actionRepeater.count > 3 && !oneOverTwoCase.visible
570+ visible: notification.type === Notification.SnapDecision && actionRepeater.count > 3 && !oneOverTwoCase.visible && notification.expanded
561571 model: notification.actions
562572 expanded: false
563573 startIndex: 2