Merge lp:~nick-dedekind/unity8/menu.width.fix into lp:unity8

Proposed by Nick Dedekind
Status: Merged
Approved by: Albert Astals Cid
Approved revision: 2771
Merged at revision: 2784
Proposed branch: lp:~nick-dedekind/unity8/menu.width.fix
Merge into: lp:unity8
Diff against target: 806 lines (+352/-194)
4 files modified
qml/ApplicationMenus/MenuPopup.qml (+178/-139)
tests/qmltests/ApplicationMenuDataLoader.qml (+13/-5)
tests/qmltests/ApplicationMenus/tst_MenuBar.qml (+5/-5)
tests/qmltests/ApplicationMenus/tst_MenuPopup.qml (+156/-45)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/menu.width.fix
Reviewer Review Type Date Requested Status
Albert Astals Cid (community) Approve
Unity8 CI Bot continuous-integration Approve
Review via email: mp+315021@code.launchpad.net

Commit message

Fixed menu layout width calculations.

Description of the change

 * Are there any related MPs required for this MP to build/function as expected? Please list.
No

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

 * If you changed the UI, has there been a design review?
N/A

To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:2771
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2944/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/3841
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=qmluitests.sh/2234
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/test-0-autopkgtest/label=amd64,release=zesty,testname=qmluitests.sh/2234
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/3869
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/3712/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/3712/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/3712/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/3712/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/3712/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3712
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/3712/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/2944/rebuild

review: Approve (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes

 * Did CI run pass? If not, please explain why.
Yes

review: Approve
2772. By Nick Dedekind

color fixes

2773. By Nick Dedekind

Auto scroll. Maximum height to bottom of screen

2774. By Nick Dedekind

Added overflow button

2775. By Nick Dedekind

enabled only when item enabled

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'qml/ApplicationMenus/MenuPopup.qml'
2--- qml/ApplicationMenus/MenuPopup.qml 2017-01-09 15:26:05 +0000
3+++ qml/ApplicationMenus/MenuPopup.qml 2017-01-18 14:44:04 +0000
4@@ -26,19 +26,7 @@
5 objectName: "menu"
6 backgroundColor: theme.palette.normal.overlay
7
8- property alias unityMenuModel: listView.model
9-
10- readonly property real __ajustedMinimumHeight: {
11- if (listView.contentHeight > __minimumHeight) {
12- return units.gu(30);
13- }
14- return Math.max(listView.contentHeight, units.gu(2));
15- }
16-
17- readonly property real __minimumWidth: units.gu(20)
18- readonly property real __minimumHeight: units.gu(30)
19- readonly property real __maximumWidth: Screen.width * 0.7
20- readonly property real __maximumHeight: Screen.height * 0.7
21+ property alias unityMenuModel: repeater.model
22
23 function show() {
24 visible = true;
25@@ -63,18 +51,23 @@
26 d.dismissAll();
27 }
28
29- implicitWidth: container.width
30- implicitHeight: MathUtils.clamp(listView.contentHeight, __ajustedMinimumHeight, __maximumHeight)
31+ implicitWidth: focusScope.width
32+ implicitHeight: focusScope.height
33
34 MenuNavigator {
35 id: d
36 objectName: "d"
37- itemView: listView
38+ itemView: repeater
39
40 property Item currentItem: null
41 property Item hoveredItem: null
42 readonly property int currentIndex: currentItem ? currentItem.__ownIndex : -1
43
44+ property real __minimumWidth: units.gu(20)
45+ property real __maximumWidth: Screen.width * 0.7
46+ property real __minimumHeight: units.gu(2)
47+ property real __maximumHeight: Screen.height * 0.7
48+
49 signal dismissAll()
50
51 onCurrentItemChanged: {
52@@ -86,13 +79,26 @@
53 }
54
55 onSelect: {
56- currentItem = listView.itemAt(index);
57+ currentItem = repeater.itemAt(index);
58+ if (currentItem) {
59+ if (currentItem.y < listView.contentY) {
60+ listView.contentY = currentItem.y;
61+ } else if (currentItem.y + currentItem.height > listView.contentY + listView.height) {
62+ listView.contentY = currentItem.y + currentItem.height - listView.height;
63+ }
64+ }
65 }
66 }
67
68+ MouseArea {
69+ // Eat events.
70+ anchors.fill: parent
71+ }
72+
73 Item {
74 id: focusScope
75- anchors.fill: parent
76+ width: container.width
77+ height: container.height
78 focus: visible
79
80 Keys.onUpPressed: d.selectPrevious(d.currentIndex)
81@@ -108,17 +114,17 @@
82 id: container
83 objectName: "container"
84
85- width: listView.contentWidth
86- height: parent.height
87+ height: MathUtils.clamp(listView.contentHeight, d.__minimumHeight, d.__maximumHeight)
88+ width: menuColumn.width
89 spacing: 0
90
91- // FIXME use ListView.header - tried but was flaky with positionViewAtIndex.
92+ // Header - scroll up
93 Item {
94- Layout.fillWidth: true;
95- Layout.maximumHeight: units.gu(3)
96- Layout.minimumHeight: units.gu(3)
97+ Layout.fillWidth: true
98+ height: units.gu(3)
99 visible: listView.contentHeight > root.height
100 enabled: !listView.atYBeginning
101+ z: 1
102
103 Rectangle {
104 color: enabled ? theme.palette.normal.overlayText :
105@@ -143,47 +149,35 @@
106 MouseArea {
107 anchors.fill: parent
108 onPressed: {
109- var index = listView.indexAt(0, listView.contentY);
110- listView.positionViewAtIndex(index-1, ListView.Beginning);
111+ var item = menuColumn.childAt(0, listView.contentY);
112+ if (item) {
113+ var previousItem = item;
114+ do {
115+ previousItem = repeater.itemAt(previousItem.__ownIndex-1);
116+ if (!previousItem) {
117+ listView.contentY = 0;
118+ return;
119+ }
120+ } while (previousItem.__isSeparator);
121+
122+ listView.contentY = previousItem.y
123+ }
124 }
125 }
126 }
127
128- ListView {
129+ // Menu Items
130+ Flickable {
131 id: listView
132- objectName: "listView"
133+ clip: interactive
134+
135 Layout.fillHeight: true
136 Layout.fillWidth: true
137- contentWidth: MathUtils.clamp(contentItem.childrenRect.width,
138- __minimumWidth,
139- __maximumWidth)
140-
141- orientation: Qt.Vertical
142- interactive: contentHeight > height
143- clip: interactive
144- highlightFollowsCurrentItem: false
145-
146- highlight: Rectangle {
147- color: "transparent"
148- border.width: units.dp(1)
149- border.color: UbuntuColors.orange
150- z: 1
151-
152- width: listView.width
153- height: d.currentItem ? d.currentItem.height : 0
154- y: d.currentItem ? d.currentItem.y : 0
155- visible: d.currentItem
156- }
157-
158- function itemAt(index) {
159- if (index > count || index < 0) return null;
160- currentIndex = index;
161- return currentItem;
162- }
163+ contentHeight: menuColumn.height
164+ interactive: height < contentHeight
165
166 MouseArea {
167- id: menuMouseArea
168- anchors.fill: listView
169+ anchors.fill: parent
170 hoverEnabled: true
171 propagateComposedEvents: true // propogate events so we send clicks to children.
172 z: 1 // on top so we override any other hovers
173@@ -195,7 +189,7 @@
174
175 if (!d.hoveredItem || !d.currentItem ||
176 !d.hoveredItem.contains(Qt.point(pos.x - d.currentItem.x, pos.y - d.currentItem.y))) {
177- d.hoveredItem = listView.itemAt(listView.indexAt(pos.x, pos.y));
178+ d.hoveredItem = menuColumn.childAt(pos.x, pos.y)
179 if (!d.hoveredItem || !d.hoveredItem.enabled)
180 return false;
181 d.currentItem = d.hoveredItem;
182@@ -216,89 +210,123 @@
183 }
184 }
185
186- delegate: Loader {
187- id: loader
188- objectName: root.objectName + "-item" + __ownIndex
189-
190- property int __ownIndex: index
191-
192- width: root.width
193- enabled: model.isSeparator ? false : model.sensitive
194-
195- sourceComponent: {
196- if (model.isSeparator) {
197- return separatorComponent;
198- }
199- return menuItemComponent;
200- }
201-
202- property Item popup: null
203-
204- Component {
205- id: menuItemComponent
206- MenuItem {
207- id: menuItem
208- menuData: model
209- objectName: loader.objectName + "-actionItem"
210-
211- action.onTriggered: {
212- d.currentItem = loader;
213-
214- if (hasSubmenu) {
215- if (!popup) {
216- var model = root.unityMenuModel.submenu(__ownIndex);
217- popup = submenuComponent.createObject(focusScope, {
218- objectName: loader.objectName + "-",
219- unityMenuModel: model,
220- x: Qt.binding(function() { return root.width }),
221- y: Qt.binding(function() { return loader.y })
222- });
223- } else if (popup) {
224- popup.visible = true;
225- }
226- popup.retreat.connect(function() {
227- popup.destroy();
228- popup = null;
229- menuItem.forceActiveFocus();
230- })
231- } else {
232- root.unityMenuModel.activate(__ownIndex);
233- }
234- }
235-
236- Connections {
237- target: d
238- onCurrentIndexChanged: {
239- if (popup && d.currentIndex != __ownIndex) {
240- popup.visible = false;
241- }
242- }
243- onDismissAll: {
244- if (popup) {
245- popup.destroy();
246- popup = null;
247- }
248- }
249- }
250- }
251- }
252-
253- Component {
254- id: separatorComponent
255- ListItems.ThinDivider {
256- objectName: loader.objectName + "-separator"
257- }
258- }
259- }
260- } // ListView
261-
262- // FIXME use ListView.footer - tried but was flaky with positionViewAtIndex.
263+ ColumnLayout {
264+ id: menuColumn
265+ spacing: 0
266+
267+ width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth)
268+
269+ Repeater {
270+ id: repeater
271+
272+ Loader {
273+ id: loader
274+ objectName: root.objectName + "-item" + __ownIndex
275+
276+ property int __ownIndex: index
277+ property bool __isSeparator: model.isSeparator
278+
279+ enabled: __isSeparator ? false : model.sensitive
280+
281+ sourceComponent: {
282+ if (model.isSeparator) {
283+ return separatorComponent;
284+ }
285+ return menuItemComponent;
286+ }
287+
288+ property Item popup: null
289+
290+ Layout.fillWidth: true
291+
292+ Component {
293+ id: menuItemComponent
294+ MenuItem {
295+ id: menuItem
296+ menuData: model
297+ objectName: loader.objectName + "-actionItem"
298+
299+ width: MathUtils.clamp(implicitWidth, d.__minimumWidth, d.__maximumWidth)
300+
301+ action.onTriggered: {
302+ d.currentItem = loader;
303+
304+ if (hasSubmenu) {
305+ if (!popup) {
306+ var model = root.unityMenuModel.submenu(__ownIndex);
307+ popup = submenuComponent.createObject(focusScope, {
308+ objectName: loader.objectName + "-",
309+ unityMenuModel: model,
310+ x: Qt.binding(function() { return root.width }),
311+ y: Qt.binding(function() {
312+ var dummy = listView.contentY; // force a recalc on contentY change.
313+ return mapToItem(container, 0, y).y;
314+ })
315+ });
316+ } else if (popup) {
317+ popup.visible = true;
318+ }
319+ popup.retreat.connect(function() {
320+ popup.destroy();
321+ popup = null;
322+ menuItem.forceActiveFocus();
323+ })
324+ } else {
325+ root.unityMenuModel.activate(__ownIndex);
326+ }
327+ }
328+
329+ Connections {
330+ target: d
331+ onCurrentIndexChanged: {
332+ if (popup && d.currentIndex != __ownIndex) {
333+ popup.visible = false;
334+ }
335+ }
336+ onDismissAll: {
337+ if (popup) {
338+ popup.destroy();
339+ popup = null;
340+ }
341+ }
342+ }
343+ }
344+ }
345+
346+ Component {
347+ id: separatorComponent
348+ ListItems.ThinDivider {
349+ objectName: loader.objectName + "-separator"
350+ implicitHeight: units.dp(2)
351+ }
352+ }
353+ }
354+
355+ }
356+ }
357+
358+ // Highlight
359+ Rectangle {
360+ color: "transparent"
361+ border.width: units.dp(1)
362+ border.color: UbuntuColors.orange
363+ z: 1
364+
365+ width: listView.width
366+ height: d.currentItem ? d.currentItem.height : 0
367+ y: d.currentItem ? d.currentItem.y : 0
368+ visible: d.currentItem
369+ }
370+
371+ } // Flickable
372+
373+ // Header - scroll down
374 Item {
375- Layout.fillWidth: true;
376- Layout.maximumHeight: units.gu(3)
377- Layout.minimumHeight: units.gu(3)
378+ Layout.fillWidth: true
379+ height: units.gu(3)
380 visible: listView.contentHeight > root.height
381 enabled: !listView.atYEnd
382+ z: 1
383
384 Rectangle {
385 color: enabled ? theme.palette.normal.overlayText :
386@@ -323,8 +351,19 @@
387 MouseArea {
388 anchors.fill: parent
389 onPressed: {
390- var index = listView.indexAt(0, listView.contentY);
391- listView.positionViewAtIndex(index+1, ListView.Beginning);
392+ var item = menuColumn.childAt(0, listView.contentY + listView.height);
393+ if (item) {
394+ var nextItem = item;
395+ do {
396+ nextItem = repeater.itemAt(nextItem.__ownIndex+1);
397+ if (!nextItem) {
398+ listView.contentY = listView.contentHeight - listView.height;
399+ return;
400+ }
401+ } while (nextItem.__isSeparator);
402+
403+ listView.contentY = nextItem.y - listView.height
404+ }
405 }
406 }
407 }
408
409=== modified file 'tests/qmltests/ApplicationMenuDataLoader.qml'
410--- tests/qmltests/ApplicationMenuDataLoader.qml 2017-01-06 14:07:36 +0000
411+++ tests/qmltests/ApplicationMenuDataLoader.qml 2017-01-18 14:44:04 +0000
412@@ -10,6 +10,7 @@
413
414 Connections {
415 id: sMgrHandler
416+ target: null
417 onSurfaceCreated: {
418 var fakeMenuPath = "/" + surface.persistentId.replace(/\W+/g, "");
419
420@@ -25,21 +26,28 @@
421 var data = [];
422 if (root === undefined) root = true;
423
424- if (prefix === undefined) prefix = "menu"
425-
426 for (var i = 0; i < length; i++) {
427
428+ var menuName = prefix;
429+ if (menuName === undefined) {
430+ var chars = Math.random() * 20;
431+ menuName = "";
432+ for (var x = 0; x < chars; x++) {
433+ menuName += String.fromCharCode((Math.random() * 26) + 65);
434+ }
435+ }
436+
437 var menuCode = String.fromCharCode(i+65);
438
439 var isSeparator = !root && separatorInterval > 0 && ((i+1) % separatorInterval == 0);
440 var row = {
441 "rowData": { // 1
442- "label": prefix + "&" + menuCode,
443+ "label": menuName + "&" + menuCode,
444 "sensitive": true,
445 "isSeparator": isSeparator,
446 "icon": "",
447 "ext": {},
448- "action": prefix + menuCode,
449+ "action": menuName + menuCode,
450 "actionState": {},
451 "isCheck": false,
452 "isRadio": false,
453@@ -49,7 +57,7 @@
454 }
455 var isSubmenu = root === undefined || root === true || (submenuInterval > 0 && ((i+1) % submenuInterval == 0));
456 if (isSubmenu && !isSeparator && depth > 1) {
457- row["submenu"] = generateTestData(length, depth-1, submenuInterval, separatorInterval, prefix + menuCode + ".", false);
458+ row["submenu"] = generateTestData(length, depth-1, submenuInterval, separatorInterval,prefix, false);
459 }
460 data[i] = row;
461 }
462
463=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuBar.qml'
464--- tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-01-09 15:26:05 +0000
465+++ tests/qmltests/ApplicationMenus/tst_MenuBar.qml 2017-01-18 14:44:04 +0000
466@@ -65,7 +65,7 @@
467
468 unityMenuModel: UnityMenuModel {
469 id: menuBackend
470- modelData: appMenuData.generateTestData(7,5,2,3,"menu")
471+ modelData: appMenuData.generateTestData(17,5,2,3)
472 }
473 }
474 }
475@@ -83,12 +83,12 @@
476
477 function init() {
478 menuBar.dismiss();
479- menuBackend.modelData = appMenuData.generateTestData(5,5,2,3,"menu")
480+ menuBackend.modelData = appMenuData.generateTestData(5,5,2,3)
481 activatedSpy.clear();
482 }
483
484 function test_mouseNavigation() {
485- menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
486+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0);
487 wait(50) // wait for row to build
488 var priv = findInvisibleChild(menuBar, "d");
489
490@@ -114,7 +114,7 @@
491 }
492
493 function test_keyboardNavigation_RightKeySelectsNextMenuItem(data) {
494- menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
495+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0);
496 var priv = findInvisibleChild(menuBar, "d");
497
498 var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0);
499@@ -139,7 +139,7 @@
500 }
501
502 function test_keyboardNavigation_LeftKeySelectsPreviousMenuItem(data) {
503- menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu");
504+ menuBackend.modelData = appMenuData.generateTestData(3,3,0,0);
505 var priv = findInvisibleChild(menuBar, "d");
506
507 var menuItem0 = findChild(menuBar, "menuBar-item0"); verify(menuItem0);
508
509=== modified file 'tests/qmltests/ApplicationMenus/tst_MenuPopup.qml'
510--- tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-01-09 15:26:05 +0000
511+++ tests/qmltests/ApplicationMenus/tst_MenuPopup.qml 2017-01-18 14:44:04 +0000
512@@ -1,4 +1,4 @@
513-/*
514+/*
515 * Copyright (C) 2016 Canonical, Ltd.
516 *
517 * This program is free software; you can redistribute it and/or modify
518@@ -28,8 +28,8 @@
519
520 Item {
521 id: root
522- width: Math.max(units.gu(100), page.width + units.gu(6))
523- height: Math.max(units.gu(50), page.height + units.gu(6))
524+ width: Math.max(units.gu(100), loader.width + units.gu(6))
525+ height: Math.max(units.gu(50), loader.height + units.gu(6))
526
527 Binding {
528 target: MouseTouchAdaptor
529@@ -39,25 +39,37 @@
530
531 ApplicationMenuDataLoader { id: appMenuData }
532
533- MenuPopup {
534- id: page
535-
536- anchors {
537- left: parent.left
538- top: parent.top
539- leftMargin: units.gu(3)
540- topMargin: units.gu(3)
541- }
542-
543- unityMenuModel: UnityMenuModel {
544- id: menuBackend
545- modelData: appMenuData.generateTestData(7,5,2,3,"menu")
546+ Loader {
547+ id: loader
548+ sourceComponent: MenuPopup {
549+ anchors {
550+ left: parent ? parent.left : undefined
551+ top: parent ? parent.top : undefined
552+ leftMargin: units.gu(3)
553+ topMargin: units.gu(3)
554+ }
555+
556+ unityMenuModel: UnityMenuModel {
557+ modelData: [{
558+ "rowData": {
559+ "label": "Short",
560+ }}, {
561+ "rowData": {
562+ "label": "This is a long menu item which tests width",
563+ }}
564+ ]
565+ }
566+
567+ Binding {
568+ target: activatedSpy
569+ property: "target"
570+ value: unityMenuModel
571+ }
572 }
573 }
574
575 SignalSpy {
576 id: activatedSpy
577- target: menuBackend
578 signalName: "activated"
579 }
580
581@@ -66,14 +78,20 @@
582 name: "MenuPopup"
583 when: windowShown
584
585+ property var menu: loader.status === Loader.Ready ? loader.item : null
586+
587 function init() {
588- page.show();
589+ loader.active = true;
590+ menu.show();
591 }
592
593 function cleanup() {
594- page.reset();
595+ menu.reset();
596 wait(100); // let the page dismiss
597 activatedSpy.clear();
598+
599+ loader.active = false;
600+ tryCompare(loader, "item", null);
601 }
602
603 // visit and verify that all the backend menus have been created
604@@ -90,6 +108,7 @@
605 // recurse into submenu
606 var submenu = rows[i]["submenu"];
607 if (submenu) {
608+ waitForRendering(menuItem);
609 mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
610 tryCompare(menuPriv, "currentItem", menuItem);
611
612@@ -113,15 +132,15 @@
613 }
614
615 function test_mouseNavigation(data) {
616- menuBackend.modelData = data.testData;
617+ menu.unityMenuModel.modelData = data.testData;
618
619- recurseMenuConstruction(data.testData, page);
620+ recurseMenuConstruction(data.testData, menu);
621 }
622
623 function test_checkableMenuTogglesOnClick() {
624- menuBackend.modelData = appMenuData.singleCheckable;
625+ menu.unityMenuModel.modelData = appMenuData.singleCheckable;
626
627- var menuItem = findChild(page, "menu-item0-actionItem");
628+ var menuItem = findChild(menu, "menu-item0-actionItem");
629 verify(menuItem);
630 compare(menuItem.action.checkable, true, "Menu item should be checkable");
631 compare(menuItem.action.checked, false, "Menu item should not be checked");
632@@ -132,13 +151,13 @@
633 }
634
635 function test_keyboardNavigation_DownKeySelectsAndOpensNextMenuItemAndRotates() {
636- menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
637-
638- var item0 = findChild(page, "menu-item0"); verify(item0);
639- var item1 = findChild(page, "menu-item1"); verify(item1);
640- var item2 = findChild(page, "menu-item2"); verify(item2);
641-
642- var priv = findInvisibleChild(page, "d");
643+ menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
644+
645+ var item0 = findChild(menu, "menu-item0"); verify(item0);
646+ var item1 = findChild(menu, "menu-item1"); verify(item1);
647+ var item2 = findChild(menu, "menu-item2"); verify(item2);
648+
649+ var priv = findInvisibleChild(menu, "d");
650
651 keyClick(Qt.Key_Down, Qt.NoModifier);
652 compare(priv.currentItem, item0, "CurrentItem should have moved to item 0");
653@@ -154,13 +173,13 @@
654 }
655
656 function test_keyboardNavigation_UpKeySelectsAndOpensPreviousMenuItemAndRotates() {
657- menuBackend.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
658-
659- var item0 = findChild(page, "menu-item0"); verify(item0);
660- var item1 = findChild(page, "menu-item1"); verify(item1);
661- var item2 = findChild(page, "menu-item2"); verify(item2);
662-
663- var priv = findInvisibleChild(page, "d");
664+ menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,0,0,"menu",false);
665+
666+ var item0 = findChild(menu, "menu-item0"); verify(item0);
667+ var item1 = findChild(menu, "menu-item1"); verify(item1);
668+ var item2 = findChild(menu, "menu-item2"); verify(item2);
669+
670+ var priv = findInvisibleChild(menu, "d");
671
672 keyClick(Qt.Key_Down, Qt.NoModifier);
673 compare(priv.currentItem, item0, "CurrentItem should have moved to item 2");
674@@ -176,17 +195,17 @@
675 }
676
677 function test_keyboardNavigation_RightKeyEntersSubMenu() {
678- menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
679-
680- var menuItem = findChild(page, "menu-item0");
681-
682- var priv = findInvisibleChild(page, "d");
683+ menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
684+
685+ var menuItem = findChild(menu, "menu-item0");
686+
687+ var priv = findInvisibleChild(menu, "d");
688 priv.currentItem = menuItem;
689
690 keyClick(Qt.Key_Right, Qt.NoModifier);
691 tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true);
692
693- var submenu0 = findChild(page, "menu-item0-menu"); verify(submenu0);
694+ var submenu0 = findChild(menu, "menu-item0-menu"); verify(submenu0);
695 var submenu0item0 = findChild(submenu0, "menu-item0-menu-item0"); verify(submenu0item0);
696
697 var submenu0Priv = findInvisibleChild(submenu0, "d"); verify(submenu0Priv);
698@@ -194,14 +213,106 @@
699 }
700
701 function test_keyboardNavigation_LeftKeyClosesSubMenu() {
702- menuBackend.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
703+ menu.unityMenuModel.modelData = appMenuData.generateTestData(3,3,1,0,"menu",false);
704
705- var menuItem = findChild(page, "menu-item0"); verify(menuItem);
706+ var menuItem = findChild(menu, "menu-item0"); verify(menuItem);
707 mouseClick(menuItem, menuItem.width/2, menuItem.height/2);
708 tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, true);
709
710 keyClick(Qt.Key_Left, Qt.NoModifier);
711 tryCompareFunction(function() { return menuItem.popup !== null && menuItem.popup.visible }, false);
712 }
713+
714+ function test_differentSizes() {
715+ var differentSizesMenu = [{
716+ "rowData": { "label": "Short" }}, {
717+ "rowData": { "label": "This is a long menu item which tests width" }
718+ }];
719+
720+ menu.unityMenuModel.modelData = differentSizesMenu;
721+
722+ waitForRendering(menu);
723+ var longWidth = menu.width;
724+ differentSizesMenu.pop();
725+ menu.unityMenuModel.modelData = differentSizesMenu;
726+
727+ waitForRendering(menu);
728+ verify(menu.width < longWidth);
729+ }
730+
731+ function test_minimumWidth() {
732+ var shortMenu = [{
733+ "rowData": { "label": "Short" }
734+ }];
735+ menu.unityMenuModel.modelData = shortMenu;
736+
737+ var priv = findInvisibleChild(menu, "d");
738+ priv.__minimumWidth = 0;
739+ priv.__maximumWidth = 1000;
740+ tryCompareFunction(function() { return menu.width > priv.__minimumWidth; }, true);
741+
742+ priv.__minimumWidth = 300;
743+ tryCompare(menu, "width", priv.__minimumWidth);
744+ }
745+
746+ function test_maximumWidth() {
747+ var longMenu = [{
748+ "rowData": { "label": "This is a long menu item which tests width" }
749+ }];
750+
751+ var priv = findInvisibleChild(menu, "d");
752+ priv.__minimumWidth = 0;
753+ priv.__maximumWidth = 100;
754+
755+ menu.unityMenuModel.modelData = longMenu;
756+ tryCompare(menu, "width", priv.__maximumWidth);
757+
758+ priv.__maximumWidth = 200;
759+ tryCompare(menu, "width", priv.__maximumWidth);
760+
761+ priv.__maximumWidth = 1200;
762+ tryCompareFunction(function() { return menu.width < priv.__maximumWidth; }, true);
763+ }
764+
765+ function test_minimumHeight() {
766+ var shortMenu = [{
767+ "rowData": { "label": "menu1" }
768+ }];
769+ menu.unityMenuModel.modelData = shortMenu;
770+
771+ var priv = findInvisibleChild(menu, "d");
772+ priv.__minimumHeight = 0;
773+ priv.__maximumHeight = 1000;
774+ tryCompareFunction(function() { return menu.height > priv.__minimumHeight; }, true);
775+
776+ priv.__minimumHeight = 300;
777+ tryCompare(menu, "height", priv.__minimumHeight);
778+ }
779+
780+ function test_maximumHeight() {
781+ var shortMenu = [{
782+ "rowData": { "label": "menu1" }}, {
783+ "rowData": { "label": "menu2" }}, {
784+ "rowData": { "label": "menu3" }}, {
785+ "rowData": { "label": "menu4" }}, {
786+ "rowData": { "label": "menu5" }}, {
787+ "rowData": { "label": "menu6" }}, {
788+ "rowData": { "label": "menu7" }}, {
789+ "rowData": { "label": "menu8" }}, {
790+ "rowData": { "label": "menu9" }
791+ }];
792+ menu.unityMenuModel.modelData = shortMenu;
793+
794+ var priv = findInvisibleChild(menu, "d");
795+ priv.__minimumHeight = 0;
796+ priv.__maximumHeight = 100;
797+ tryCompare(menu, "height", priv.__maximumHeight);
798+
799+ priv.__maximumHeight = 200;
800+ tryCompare(menu, "height", priv.__maximumHeight);
801+
802+ priv.__maximumHeight = 1200;
803+ tryCompareFunction(function() { return menu.height < priv.__maximumHeight; }, true);
804+ }
805 }
806 }

Subscribers

People subscribed via source and target branches