on xenial help sign in
make pinlockscreen adjust better to larger displays
5ea5f5cMichael Zanetti
qml/Components/PinLockscreen.qml+151−142
@@ -19,16 +19,12 @@ import Ubuntu.Components 0.1
19import Ubuntu.Components.ListItems 0.1
19import Ubuntu.Components.ListItems 0.1
20import "../Components"
20import "../Components"
21
21
22−Column {
22+Item {
23 id: root
23 id: root
24− y: units.gu(4)
25− spacing: units.gu(2)
26
24
27 property string infoText
25 property string infoText
28 property string retryText
26 property string retryText
29 property string errorText
27 property string errorText
30− property int padWidth: units.gu(34)
31− property int padHeight: units.gu(28)
32 property int minPinLength: -1
28 property int minPinLength: -1
33 property int maxPinLength: -1
29 property int maxPinLength: -1
34 property bool showCancelButton: true
30 property bool showCancelButton: true
@@ -49,123 +45,151 @@ Column {
49 }
45 }
50
46
51 Column {
47 Column {
52− id: shakeContainer
48+ anchors {
53− anchors.horizontalCenter: parent.horizontalCenter
49+ left: parent.left;
54− width: parent.width
50+ right: parent.right;
55− spacing: units.gu(1)
51+ verticalCenter: parent.verticalCenter;
56−
52+ verticalCenterOffset: Math.max(-units.gu(10), -(root.height - height) / 2) + units.gu(4)
57− Label {
58− id: infoField
59− objectName: "infoTextLabel"
60− fontSize: "large"
61− color: "#f3f3e7"
62− anchors.horizontalCenter: parent.horizontalCenter
63− text: root.infoText
64 }
53 }
54+ spacing: units.gu(2)
65
55
66− Item {
56+ Column {
67− id: pinContainer
57+ id: shakeContainer
68− anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
58+ anchors.horizontalCenter: parent.horizontalCenter
59+ width: parent.width
69− height: units.gu(4)
60+ spacing: units.gu(1)
70
61
71− Row {
62+ Label {
72− id: pinentryField
63+ id: infoField
73− objectName: "pinentryField"
64+ objectName: "infoTextLabel"
65+ fontSize: "large"
66+ color: "#f3f3e7"
74 anchors.horizontalCenter: parent.horizontalCenter
67 anchors.horizontalCenter: parent.horizontalCenter
75− anchors.verticalCenter: parent.verticalCenter
68+ text: root.infoText
76− spacing: Math.max(0, Math.min(units.gu(3), (parent.width / root.maxPinLength) - units.gu(3)))
69+ }
77
70
71+ Item {
72+ id: pinContainer
73+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
74+ height: units.gu(4)
75+
76+ Row {
77+ id: pinentryField
78+ objectName: "pinentryField"
79+ anchors.horizontalCenter: parent.horizontalCenter
80+ anchors.verticalCenter: parent.verticalCenter
81+ spacing: Math.max(0, Math.min(units.gu(3), (parent.width / root.maxPinLength) - units.gu(3)))
82+
78− property string text
83+ property string text
79− property bool incorrectOverride: false
84+ property bool incorrectOverride: false
85+
86+ Repeater {
87+ model: pinentryField.text.length
88+ delegate: Rectangle {
89+ color: "#f3f3e7"
90+ width: Math.min(units.gu(2), (pinContainer.width - pinContainer.height*2 ) / (root.maxPinLength >= 0 ? root.maxPinLength : 16))
91+ height: width
92+ radius: width / 2
93+ }
94+ }
80
95
81− Repeater {
96+ function appendNumber(number) {
97+ if (incorrectOverride) {
98+ incorrectOverride = false;
99+ }
100+
82− model: pinentryField.text.length
101+ pinentryField.text = pinentryField.text + number
83− delegate: Rectangle {
102+
84− color: "#f3f3e7"
103+ if (root.minPinLength > 0 && root.maxPinLength > 0
85− width: Math.min(units.gu(2), (pinContainer.width - pinContainer.height*2 ) / (root.maxPinLength >= 0 ? root.maxPinLength : 16))
104+ && root.minPinLength == root.maxPinLength && pinentryField.text.length == root.minPinLength) {
86− height: width
105+ root.entered(pinentryField.text)
87− radius: width / 2
106+ }
107+ }
108+
109+ function backspace() {
110+ pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
88 }
111 }
89 }
112 }
113+ Label {
114+ id: wrongNoticeLabel
115+ objectName: "wrongNoticeLabel"
116+ fontSize: "x-large"
117+ color: "#f3f3e7"
118+ anchors.horizontalCenter: parent.horizontalCenter
119+ horizontalAlignment: Text.AlignHCenter
120+ text: root.errorText
121+ visible: pinentryField.incorrectOverride
122+ scale: Math.min(1, parent.width / width)
123+ }
124+
125+ AbstractButton {
126+ objectName: "backspaceIcon"
127+ anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
128+ width: height
129+ enabled: root.entryEnabled
90
130
91− function appendNumber(number) {
131+ Icon {
92− if (incorrectOverride) {
132+ anchors.fill: parent
93− incorrectOverride = false;
133+ name: "erase"
134+ color: "#f3f3e7"
94 }
135 }
95
136
96− pinentryField.text = pinentryField.text + number
137+ opacity: (pinentryField.text.length > 0 && !pinentryField.incorrectOverride) ? 1 : 0
97
138
98− if (root.minPinLength > 0 && root.maxPinLength > 0
139+ Behavior on opacity {
99− && root.minPinLength == root.maxPinLength && pinentryField.text.length == root.minPinLength) {
140+ UbuntuNumberAnimation {}
100− root.entered(pinentryField.text)
101 }
141 }
102− }
103
142
104− function backspace() {
143+ onClicked: pinentryField.backspace()
105− pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
106 }
144 }
107 }
145 }
146+
108 Label {
147 Label {
109− id: wrongNoticeLabel
110− objectName: "wrongNoticeLabel"
148+ objectName: "retryLabel"
111− fontSize: "x-large"
149+ fontSize: "x-small"
112 color: "#f3f3e7"
150 color: "#f3f3e7"
113 anchors.horizontalCenter: parent.horizontalCenter
151 anchors.horizontalCenter: parent.horizontalCenter
114− horizontalAlignment: Text.AlignHCenter
115− text: root.errorText
152+ text: root.retryText || " "
116− visible: pinentryField.incorrectOverride
117− scale: Math.min(1, parent.width / width)
118− }
119−
120− AbstractButton {
121− objectName: "backspaceIcon"
122− anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
123− width: height
124− enabled: root.entryEnabled
125−
126− Icon {
127− anchors.fill: parent
128− name: "erase"
129− color: "#f3f3e7"
130− }
131−
132− opacity: (pinentryField.text.length > 0 && !pinentryField.incorrectOverride) ? 1 : 0
133−
134− Behavior on opacity {
135− UbuntuNumberAnimation {}
136− }
137−
138− onClicked: pinentryField.backspace()
139 }
153 }
140 }
154 }
141
155
142− Label {
156+ ThinDivider {
143− objectName: "retryLabel"
157+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
144− fontSize: "x-small"
145− color: "#f3f3e7"
146− anchors.horizontalCenter: parent.horizontalCenter
147− text: root.retryText || " "
148 }
158 }
149− }
150−
151− ThinDivider {
152− anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
153− }
154−
155− Grid {
156− id: numbersGrid
157− anchors { horizontalCenter: parent.horizontalCenter }
158− columns: 3
159−
160− property int buttonHeight: units.gu(8)
161− property int buttonWidth: units.gu(12)
162−
163− Repeater {
164− model: 9
165
159
160+ Grid {
161+ id: numbersGrid
162+ objectName: "numbersGrid"
163+ anchors { horizontalCenter: parent.horizontalCenter }
164+ columns: 3
165+
166+ property int maxWidth: Math.min(units.gu(50), root.width - units.gu(8))
167+ property int buttonWidth: maxWidth / 3
168+ property int buttonHeight: buttonWidth * 2 / 3
169+
170+ Repeater {
171+ model: 9
172+
173+ PinPadButton {
174+ objectName: "pinPadButton" + text
175+ text: index + 1
176+ height: numbersGrid.buttonHeight
177+ width: numbersGrid.buttonWidth
178+ enabled: root.entryEnabled && (root.maxPinLength == -1 ||
179+ pinentryField.text.length < root.maxPinLength ||
180+ pinentryField.incorrectOverride)
181+
182+ onClicked: {
183+ pinentryField.appendNumber(index + 1)
184+ }
185+ }
186+ }
187+ Item {
188+ height: numbersGrid.buttonHeight
189+ width: numbersGrid.buttonWidth
190+ }
166 PinPadButton {
191 PinPadButton {
167− objectName: "pinPadButton" + text
192+ text: "0"
168− text: index + 1
169 height: numbersGrid.buttonHeight
193 height: numbersGrid.buttonHeight
170 width: numbersGrid.buttonWidth
194 width: numbersGrid.buttonWidth
171 enabled: root.entryEnabled && (root.maxPinLength == -1 ||
195 enabled: root.entryEnabled && (root.maxPinLength == -1 ||
@@ -173,56 +197,41 @@ Column {
173 pinentryField.incorrectOverride)
197 pinentryField.incorrectOverride)
174
198
175 onClicked: {
199 onClicked: {
176− pinentryField.appendNumber(index + 1)
200+ pinentryField.appendNumber(0)
177 }
201 }
178 }
202 }
179− }
180− Item {
203+ Item {
181− height: numbersGrid.buttonHeight
182− width: numbersGrid.buttonWidth
183− }
184− PinPadButton {
185− text: "0"
186− height: numbersGrid.buttonHeight
204+ height: numbersGrid.buttonHeight
187− width: numbersGrid.buttonWidth
205+ width: numbersGrid.buttonWidth
188− enabled: root.entryEnabled && (root.maxPinLength == -1 ||
189− pinentryField.text.length < root.maxPinLength ||
190− pinentryField.incorrectOverride)
191−
192− onClicked: {
193− pinentryField.appendNumber(0)
194 }
206 }
195− }
196− Item {
197− height: numbersGrid.buttonHeight
198− width: numbersGrid.buttonWidth
199− }
200− PinPadButton {
207+ PinPadButton {
201− iconName: "close"
208+ iconName: "close"
202− height: units.gu(5) // visual spec has this row a little closer in
209+ height: units.gu(5) // visual spec has this row a little closer in
203− width: numbersGrid.buttonWidth
210+ width: numbersGrid.buttonWidth
204
211
205− onClicked: root.cancel()
212+ onClicked: root.cancel()
206− visible: root.showCancelButton
213+ visible: root.showCancelButton
207− }
214+ }
208− Item {
215+ Item {
209− height: units.gu(5)
216+ height: units.gu(5)
217+ width: numbersGrid.buttonWidth
218+ }
219+ PinPadButton {
220+ iconName: "tick"
221+ objectName: "confirmButton"
222+ height: units.gu(5)
210− width: numbersGrid.buttonWidth
223+ width: numbersGrid.buttonWidth
224+ enabled: root.enabled && pinentryField.text.length >= root.minPinLength
225+ visible: root.minPinLength == -1 || root.minPinLength !== root.maxPinLength
226+
227+ onClicked: root.entered(pinentryField.text)
228+ }
211 }
229 }
212− PinPadButton {
230+ WrongPasswordAnimation {
213− iconName: "tick"
231+ id: wrongPasswordAnimation
214− objectName: "confirmButton"
232+ objectName: "wrongPasswordAnimation"
215− height: units.gu(5)
233+ target: shakeContainer
216− width: numbersGrid.buttonWidth
217− enabled: root.enabled && pinentryField.text.length >= root.minPinLength
218− visible: root.minPinLength == -1 || root.minPinLength !== root.maxPinLength
219−
220− onClicked: root.entered(pinentryField.text)
221 }
234 }
222 }
235 }
223− WrongPasswordAnimation {
224− id: wrongPasswordAnimation
225− objectName: "wrongPasswordAnimation"
226− target: shakeContainer
227− }
228}
236}
237+
tests/qmltests/Components/tst_Lockscreen.qml+26
@@ -173,6 +173,10 @@ Rectangle {
173 function cleanup() {
173 function cleanup() {
174 lockscreen.clear(false);
174 lockscreen.clear(false);
175 delayMinutesTextField.text = "0"
175 delayMinutesTextField.text = "0"
176+
177+ // Reset sizing
178+ root.width = units.gu(80)
179+ root.height = units.gu(76)
176 }
180 }
177
181
178 function waitForLockscreenReady() {
182 function waitForLockscreenReady() {
@@ -450,6 +454,28 @@ Rectangle {
450 var label = findChild(lockscreen, "deviceLockedLabel")
454 var label = findChild(lockscreen, "deviceLockedLabel")
451 compare(label.text, "Device Locked")
455 compare(label.text, "Device Locked")
452 }
456 }
457+
458+ function test_resize_data() {
459+ return [
460+ { tag: "small", width: units.gu(40), height: units.gu(76) },
461+ { tag: "medium", width: units.gu(50), height: units.gu(86) },
462+ { tag: "large", width: units.gu(60), height: units.gu(96) },
463+ { tag: "x-large", width: units.gu(80), height: units.gu(116) },
464+ ]
465+ }
466+
467+ function test_resize(data) {
468+ var controlsAreaWidth = lockscreen.anchors.rightMargin;
469+ root.width = data.width + controlsAreaWidth;
470+ root.height = data.height;
471+ waitForRendering(root);
472+
473+ var numbersGrid = findChild(lockscreen, "numbersGrid");
474+ // Make sure the numbers pad keeps a 4gu margin on left/right but doesn't grow larger than 50 gu's width.
475+ // For rounding reasons it might be off 1 pixel. Let's make sure it's within +/- 1 pixel of what we expect
476+ verify(numbersGrid.width >= Math.min(units.gu(50), data.width - units.gu(8)) - 1);
477+ verify(numbersGrid.width <= Math.min(units.gu(50), data.width - units.gu(8)) + 1);
478+ }
453 }
479 }
454
480
455 SignalSpy {
481 SignalSpy {