Unity 8
Page.qml
1 /*
2  * Copyright (C) 2013-2016 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.4
18 import Ubuntu.Components 1.3
19 import Wizard 0.1
20 
21 Item {
22  readonly property real maximumContentWidth: units.gu(50)
23  readonly property bool wideMode: width > units.gu(90) && width > height
24  readonly property bool contentAnimationRunning: contentAnimation.running
25 
26  readonly property real buttonMargin: units.gu(3)
27  readonly property real buttonWidth: (width - buttonMargin * 2) / 2 -
28  buttonMargin / 2
29  readonly property real buttonBarHeight: units.gu(5)
30  readonly property real titleRectHeight: customTitle ? units.gu(10) : units.gu(16)
31 
32  readonly property real topMargin: units.gu(11)
33  readonly property real bottomMargin: units.gu(3)
34  readonly property real leftMargin: Math.max(units.gu(3), (width - maximumContentWidth) / 3)
35  readonly property real rightMargin: leftMargin
36  readonly property real customMargin: wideMode ? units.gu(8) : units.gu(4) // margin for the content
37  readonly property real staticMargin: units.gu(3)
38 
39  // colors
40  readonly property color backgroundColor: "#fdfdfd"
41  readonly property color dividerColor: UbuntuColors.silk
42  readonly property color textColor: UbuntuColors.slate
43  readonly property color errorColor: theme.palette.normal.negative
44  readonly property color okColor: theme.palette.normal.positive
45  readonly property color whiteColor: "white" // workaround for a UITK bug
46 
47  // If you want to skip a page, mark skipValid false while you figure out
48  // whether to skip, then set it to true once you've determined the value
49  // of the skip property.
50  property bool skipValid: true
51  property bool skip: false
52 
53  property bool hasBackButton: true
54  property string backButtonText: i18n.ctr("Button: Go back one page in the Wizard", "Back")
55  property bool customBack: false
56  property bool customTitle: false
57  property alias forwardButtonSourceComponent: forwardButton.sourceComponent
58  property alias content: contentHolder
59  property bool lastPage: false
60  property bool buttonBarVisible: true
61 
62  property string title: ""
63 
64  signal backClicked()
65 
66  visible: false
67  anchors.fill: parent
68 
69  Timer {
70  id: indicatorTimer
71  interval: 1000
72  triggeredOnStart: true
73  repeat: true
74  running: System.wizardEnabled
75  onTriggered: {
76  indicatorTime.text = Qt.formatTime(new Date(), "h:mm")
77  }
78  }
79 
80  // page header
81  Image {
82  id: titleRect
83  visible: !lastPage
84  anchors {
85  top: parent.top
86  left: parent.left
87  right: parent.right
88  }
89  source: customTitle ? "" : (wideMode ? "Pages/data/Desktop_header_bkg.png" : "Pages/data/Phone_header_bkg.png")
90  height: titleRectHeight
91  clip: true
92 
93  // page title
94  Label {
95  id: titleLabel
96  property real animatedTopMargin: 0
97  anchors {
98  left: parent.left
99  right: parent.right
100  bottom: parent.bottom
101  bottomMargin: bottomMargin
102  leftMargin: staticMargin
103  rightMargin: rightMargin
104  topMargin: titleLabel.animatedTopMargin
105  }
106  text: title
107  color: customTitle ? textColor : backgroundColor
108  fontSize: customTitle ? "large" : "x-large"
109  font.weight: Font.Light
110  wrapMode: Text.WordWrap
111  maximumLineCount: 2
112  elide: Text.ElideRight
113  }
114 
115  // indicators
116  Row {
117  id: indicatorRow
118  visible: !customTitle
119  anchors {
120  top: parent.top
121  right: parent.right
122  topMargin: units.gu(.5)
123  rightMargin: units.gu(.5)
124  }
125  height: units.gu(2)
126  spacing: units.gu(1)
127 
128  Icon {
129  id: indicatorSim
130  anchors.verticalCenter: parent.verticalCenter
131  name: "no-simcard"
132  height: parent.height
133  width: height
134  visible: !(root.simManager0.present || root.simManager1.present) && root.modemManager.modems.length > 0
135  color: "white"
136  }
137 
138  Icon {
139  id: indicatorNet
140  anchors.verticalCenter: parent.verticalCenter
141  name: Status.networkIcon
142  height: parent.height
143  width: height
144  color: "white"
145  }
146 
147  Icon {
148  id: indicatorBattery
149  anchors.verticalCenter: parent.verticalCenter
150  name: Status.batteryIcon
151  height: parent.height
152  width: height * 1.4 // the battery icon is not rectangular :/
153  color: "white"
154  }
155 
156  Label {
157  id: indicatorTime
158  anchors.verticalCenter: parent.verticalCenter
159  color: whiteColor
160  fontSize: "small"
161  }
162  }
163  }
164 
165  // content
166  Item {
167  id: contentHolder
168  property real animatedMargin: 0
169  property real animatedTopMargin: 0
170  anchors {
171  top: titleRect.bottom
172  left: parent.left
173  right: parent.right
174  bottom: buttonBarVisible ? buttonRect.top : parent.bottom
175  leftMargin: content.animatedMargin
176  rightMargin: -content.animatedMargin
177  topMargin: content.animatedTopMargin
178  }
179  visible: opacity > 0
180  }
181 
182  // button bar
183  Rectangle {
184  id: buttonRect
185  visible: buttonBarVisible
186  anchors {
187  bottom: parent.bottom
188  bottomMargin: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
189  left: parent.left
190  right: parent.right
191  }
192  height: buttonBarHeight
193  color: "#f5f5f5"
194  z: content.z + 1
195 
196  StackButton {
197  id: backButton
198  objectName: "backButton"
199  width: buttonWidth
200  anchors {
201  left: parent.left
202  bottom: parent.bottom
203  leftMargin: staticMargin
204  verticalCenter: parent.verticalCenter
205  }
206  text: backButtonText
207  visible: pageStack.depth > 1 && hasBackButton
208  backArrow: true
209 
210  onClicked: customBack ? backClicked() : pageStack.prev()
211  }
212 
213  Loader {
214  id: forwardButton
215  objectName: "forwardButton"
216  width: buttonWidth
217  anchors {
218  right: parent.right
219  bottom: parent.bottom
220  rightMargin: staticMargin
221  verticalCenter: parent.verticalCenter
222  }
223  }
224  }
225 
226  // transitions
227  function aboutToShow(duration, direction) {
228  startContentAnimation(duration, direction)
229  startControlsAnimation(duration)
230  }
231 
232  function aboutToShowSecondary(duration) {
233  secondaryAnimation.restart()
234  startControlsAnimation(duration)
235  }
236 
237  function startContentAnimation(duration, direction) {
238  contentAnimation.animationDurationBase = duration
239  contentAnimation.direction = direction
240  contentAnimation.restart()
241  }
242 
243  function startControlsAnimation(showDuration) {
244  actionsShowAnimation.showDuration = showDuration
245  actionsShowAnimation.restart()
246  }
247 
248  SequentialAnimation { // animation for the button bar
249  id: actionsShowAnimation
250  property int showDuration: 0
251  PropertyAction {
252  target: buttonRect
253  property: 'opacity'
254  value: 0
255  }
256  PauseAnimation { duration: Math.max(0, actionsShowAnimation.showDuration - UbuntuAnimation.SnapDuration) }
257  NumberAnimation {
258  target: buttonRect
259  property: 'opacity'
260  to: 1
261  duration: UbuntuAnimation.SnapDuration
262  }
263  }
264 
265  SequentialAnimation { // animations for the content
266  id: contentAnimation
267  objectName: "contentAnimation"
268  property int animationDurationBase: UbuntuAnimation.BriskDuration
269  readonly property int additionalDuration: 200
270  property int direction: Qt.LeftToRight
271  ScriptAction { // direction of the effect
272  script: {
273  if (contentAnimation.direction === Qt.LeftToRight) {
274  content.animatedMargin = -content.width;
275  } else {
276  content.animatedMargin = content.width;
277  }
278  }
279  }
280  ParallelAnimation {
281  NumberAnimation { // the slide-in animation
282  targets: content
283  property: 'animatedMargin'
284  to: 0
285  duration: contentAnimation.animationDurationBase + contentAnimation.additionalDuration
286  easing.type: Easing.OutCubic
287  }
288  NumberAnimation { // opacity animation
289  targets: [titleLabel,content]
290  property: 'opacity'
291  from: 0
292  to: 1
293  duration: contentAnimation.animationDurationBase
294  }
295  }
296  }
297 
298  ParallelAnimation { // animation for the secondary pages
299  id: secondaryAnimation
300  objectName: "secondaryAnimation"
301  NumberAnimation { // the slide-up animation
302  target: titleLabel
303  property: 'animatedTopMargin'
304  from: content.height
305  to: customMargin
306  duration: UbuntuAnimation.BriskDuration
307  easing: UbuntuAnimation.StandardEasing
308  }
309  NumberAnimation {
310  target: content
311  property: 'animatedTopMargin'
312  from: content.height
313  to: 0
314  duration: UbuntuAnimation.BriskDuration
315  easing: UbuntuAnimation.StandardEasing
316  }
317  NumberAnimation { // opacity animation
318  target: content
319  property: 'opacity'
320  from: 0
321  to: 1
322  duration: UbuntuAnimation.BriskDuration
323  }
324  }
325 }