~josharenson/unity8/fix-greeter-password-focus

« back to all changes in this revision

Viewing changes to qml/Dash/DashNavigation.qml

  • Committer: Josh Arenson
  • Date: 2016-03-25 19:53:42 UTC
  • mfrom: (1978.1.6 sessions-model)
  • mto: This revision was merged to the branch mainline in revision 1986.
  • Revision ID: joshua.arenson@canonical.com-20160325195342-ibax564aavo3lk2i
merge prereq

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import QtQuick 2.4
18
18
import Ubuntu.Components 1.3
19
19
import Dash 0.1
20
 
import "../Components"
21
20
 
22
21
Item {
23
22
    id: root
24
23
    objectName: "dashNavigation"
25
24
 
 
25
    // set by parent
26
26
    property var scope: null
27
 
    property var scopeStyle: null
28
 
 
29
 
    property alias windowWidth: blackRect.width
30
 
    property alias windowHeight: blackRect.height
31
 
    readonly property var openList: {
32
 
        if (navigationButton.showList) return navigationButton.listView;
33
 
        if (altNavigationButton.showList) return altNavigationButton.listView;
34
 
        return null;
35
 
    }
36
 
    readonly property bool disableParentInteractive: {
37
 
        return navigationButton.showList || altNavigationButton.showList ||
38
 
               navigationButton.inverseMousePressed || altNavigationButton.inverseMousePressed;
39
 
    }
40
 
 
41
 
    // FIXME this is only here for highlight purposes (see Background.qml, too)
42
 
    readonly property var background: backgroundItem
 
27
    property real availableHeight
 
28
 
 
29
    signal leafClicked()
 
30
 
 
31
    // internal
 
32
    readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
 
33
    // Are we drilling down the tree or up?
 
34
    property bool isEnteringChildren: false
43
35
 
44
36
    visible: height != 0
45
 
    height: navigationButton.currentNavigation || altNavigationButton.currentNavigation ? units.gu(5) : 0
46
 
 
47
 
    QtObject {
48
 
        id: d
49
 
        readonly property color foregroundColor: root.scopeStyle
50
 
                                                 ? root.scopeStyle.getTextColor(backgroundItem.luminance)
51
 
                                                 : theme.palette.normal.baseText
52
 
        readonly property bool bothVisible: altNavigationButton.visible && navigationButton.visible
53
 
        readonly property real navigationWidth: root.width >= units.gu(60) ? units.gu(40) : root.width
54
 
        readonly property real buttonWidth: navigationWidth / (bothVisible ? 2 : 1)
55
 
    }
56
 
 
57
 
    Rectangle {
58
 
        id: blackRect
59
 
        objectName: "blackRect"
60
 
        color: "black"
61
 
        opacity: openList && openList.currentItem && openList.currentItem.visible ? 0.5 : 0
62
 
        Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
63
 
        anchors { left: parent.left; right: parent.right }
64
 
        visible: opacity > 0
65
 
    }
66
 
 
67
 
    Background {
68
 
        id: backgroundItem
69
 
        anchors.fill: parent
70
 
        style: scopeStyle ? scopeStyle.navigationBackground : "color:///#f5f5f5"
71
 
    }
72
 
 
73
 
    Image {
74
 
        fillMode: Image.Stretch
75
 
        source: scopeStyle.backgroundLuminance > 0.2 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
76
 
        anchors { top: parent.bottom; left: parent.left; right: parent.right }
77
 
    }
78
 
 
79
 
    DashNavigationButton {
80
 
        id: altNavigationButton
81
 
        objectName: "altNavigationButton"
82
 
        height: root.height
83
 
        width: d.buttonWidth
84
 
        scope: root.scope
85
 
        scopeStyle: root.scopeStyle
86
 
        foregroundColor: d.foregroundColor
87
 
        listView.width: d.navigationWidth
88
 
        isAltNavigation: true
89
 
        showDivider: navigationButton.visible || root.width > d.navigationWidth
90
 
        // needed so that InverseMouseArea is above navigationButton
91
 
        z: listView.height > 0 ? 1 : 0
92
 
    }
93
 
 
94
 
    DashNavigationButton {
95
 
        id: navigationButton
96
 
        objectName: "navigationButton"
97
 
        height: root.height
98
 
        width: altNavigationButton.visible ? d.buttonWidth : d.navigationWidth
99
 
        x: altNavigationButton.visible ? d.buttonWidth : 0
100
 
        scope: root.scope
101
 
        scopeStyle: root.scopeStyle
102
 
        foregroundColor: d.foregroundColor
103
 
        listView.width: d.navigationWidth
104
 
        listView.x: -x
105
 
        showDivider: root.width > d.navigationWidth
106
 
    }
107
 
 
108
 
    Image {
109
 
        fillMode: Image.Stretch
110
 
        source: backgroundItem.luminance > 0.7 ? "graphics/navigation_shadow.png" : "graphics/navigation_shadow_light.png"
111
 
        x: navigationButton.listView.height > 0 ? altNavigationButton.x : navigationButton.x
112
 
        width: d.buttonWidth
113
 
        rotation: 180
114
 
        anchors.bottom: parent.bottom
115
 
        visible: d.bothVisible && (navigationButton.listView.height > 0 || altNavigationButton.listView.height > 0)
116
 
    }
 
37
    implicitHeight: scope && scope.hasNavigation ? navigationListView.y + navigationListView.height : 0
 
38
 
 
39
    function resetNavigation() {
 
40
        if (navigationModel.count > 1) {
 
41
            clear();
 
42
        }
 
43
    }
 
44
 
 
45
    Column {
 
46
        id: headersColumn
 
47
        anchors {
 
48
            top: parent.top
 
49
            left: parent.left
 
50
            right: parent.right
 
51
        }
 
52
 
 
53
        function pop(popsNeeded) {
 
54
            if (popsNeeded == 0)
 
55
                return;
 
56
            isEnteringChildren = false;
 
57
            navigationListView.currentIndex = navigationListView.currentIndex - popsNeeded;
 
58
            navigationModel.setProperty(navigationListView.currentIndex, "nullifyNavigation", false);
 
59
            navigationModel.remove(navigationModel.count - popsNeeded, popsNeeded);
 
60
 
 
61
            popsNeeded = Math.min(headersModel.count, popsNeeded);
 
62
            // This is effectively deleting ourselves, so needs to be the last thing of the function
 
63
            headersModel.remove(headersModel.count - popsNeeded, popsNeeded);
 
64
        }
 
65
 
 
66
        Repeater {
 
67
            model: ListModel {
 
68
                id: headersModel
 
69
                // Roles
 
70
                // headerText: the text to show
 
71
                // navigationId: the navigation Id that represents
 
72
                // parentNavigationId: the parent navigation Id
 
73
            }
 
74
            delegate: DashNavigationHeader {
 
75
                objectName: "dashNavigationHeader" + index
 
76
                height: index == 0 && headersModel.count > 1 ? 0 : units.gu(5)
 
77
                width: headersColumn.width
 
78
 
 
79
                backVisible: index != 0
 
80
                text: headerText
 
81
 
 
82
                onBackClicked: {
 
83
                    scope.setNavigationState(parentNavigationId);
 
84
 
 
85
                    var popsNeeded = headersModel.count - index;
 
86
                    headersColumn.pop(popsNeeded);
 
87
                }
 
88
 
 
89
                onTextClicked: {
 
90
                    scope.setNavigationState(navigationId);
 
91
 
 
92
                    var popsNeeded = headersModel.count - index - 1;
 
93
                    headersColumn.pop(popsNeeded);
 
94
 
 
95
                    root.leafClicked();
 
96
                }
 
97
            }
 
98
        }
 
99
    }
 
100
 
 
101
    ListView {
 
102
        id: navigationListView
 
103
        objectName: "navigationListView"
 
104
        orientation: ListView.Horizontal
 
105
        interactive: false
 
106
        model: ListModel {
 
107
            id: navigationModel
 
108
            // We have two roles
 
109
            // navigationId: the navigation id of the navigation the list represents
 
110
            // nullifyNavigation: overrides navigationId to be null
 
111
            //                    This is used to "clear" the delegate when going "right" on the tree
 
112
        }
 
113
        anchors {
 
114
            top: headersColumn.bottom
 
115
            left: parent.left
 
116
            right: parent.right
 
117
        }
 
118
        readonly property int maxHeight: root.availableHeight - navigationListView.y
 
119
        property int prevHeight: maxHeight
 
120
        height: currentItem ? currentItem.height : maxHeight
 
121
 
 
122
        onHeightChanged: {
 
123
            if (currentItem) {
 
124
                prevHeight = currentItem.desiredHeight;
 
125
            }
 
126
        }
 
127
        highlightMoveDuration: UbuntuAnimation.FastDuration
 
128
        delegate: DashNavigationList {
 
129
            objectName: "navigation" + index
 
130
            visible: height > 0
 
131
            width: navigationListView.width
 
132
            property real desiredHeight: {
 
133
                if (navigation && navigation.loaded && x == navigationListView.contentX)
 
134
                {
 
135
                    return Math.min(implicitHeight, navigationListView.maxHeight);
 
136
                } else {
 
137
                    return navigationListView.prevHeight;
 
138
                }
 
139
            }
 
140
            height: desiredHeight
 
141
            navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
 
142
            currentNavigation: root.currentNavigation
 
143
            onEnterNavigation: { // var newNavigationId, string newNavigationLabel, bool hasChildren
 
144
                scope.setNavigationState(newNavigationId);
 
145
                // We only need to add a new item to the model
 
146
                // if we have children, otherwise just load it
 
147
                if (hasChildren) {
 
148
                    isEnteringChildren = true;
 
149
                    navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
 
150
                    headersModel.append({"headerText": newNavigationLabel,
 
151
                                         "navigationId": newNavigationId,
 
152
                                         "parentNavigationId": navigationId
 
153
                                        });
 
154
                    navigationListView.currentIndex++;
 
155
                } else {
 
156
                    root.leafClicked();
 
157
                }
 
158
            }
 
159
        }
 
160
        onContentXChanged: {
 
161
            if (navigationListView.highlightMoveDuration == 0)
 
162
                return;
 
163
 
 
164
            if (contentX == width * navigationListView.currentIndex) {
 
165
                if (isEnteringChildren) {
 
166
                    navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
 
167
                }
 
168
            }
 
169
        }
 
170
    }
 
171
 
 
172
    property bool isFirstLoad: false
 
173
    onScopeChanged: clear();
 
174
    function clear() {
 
175
        navigationModel.clear();
 
176
        headersModel.clear();
 
177
        isFirstLoad = true;
 
178
    }
 
179
    function setNewNavigation() {
 
180
        if (isFirstLoad && currentNavigation && currentNavigation.loaded) {
 
181
            isFirstLoad = false;
 
182
            if (currentNavigation.count > 0) {
 
183
                navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
 
184
            } else {
 
185
                navigationModel.append({"navigationId": currentNavigation.parentNavigationId, "nullifyNavigation": false});
 
186
            }
 
187
            headersModel.append({"headerText": currentNavigation.allLabel != "" ? currentNavigation.allLabel : currentNavigation.label,
 
188
                                 "navigationId": currentNavigation.navigationId,
 
189
                                 "parentNavigationId": currentNavigation.parentNavigationId
 
190
                                });
 
191
        }
 
192
    }
 
193
    Connections {
 
194
        target: currentNavigation
 
195
        onLoadedChanged: setNewNavigation();
 
196
    }
 
197
    onCurrentNavigationChanged: setNewNavigation();
117
198
}