Lomiri
IndicatorItem.qml
1/*
2 * Copyright 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 Lesser 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 Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.12
18import Lomiri.Components 1.3
19import Lomiri.Settings.Components 0.1
20import QMenuModel 1.0
21
22IndicatorDelegate {
23 id: root
24
25 property string identifier
26 property alias title: indicatorName.text
27 property alias leftLabel: leftLabelItem.text
28 property alias rightLabel: rightLabelItem.text
29 property var icons: undefined
30 property bool expanded: false
31 property bool selected: false
32 property real iconHeight: units.gu(2)
33 readonly property color color: {
34 if (!expanded) return theme.palette.normal.backgroundText;
35 if (!selected) return theme.palette.disabled.backgroundText;
36 return theme.palette.normal.backgroundText;
37 }
38
39 implicitWidth: mainItems.width
40
41 // Prevent ListView from removing us from the view while expanding.
42 // If we're the PanelBar's initial item, our removal will make it lose
43 // track of us and cause its positioning to go wrong.
44 ListView.delayRemove: stateTransition.running
45
46 MouseArea {
47 readonly property int stepUp: 1
48 readonly property int stepDown: -1
49
50 anchors.fill: parent
51 acceptedButtons: Qt.MiddleButton
52 onClicked: {
53 if ((!expanded || selected) && secondaryAction.valid) {
54 secondaryAction.activate();
55 }
56 }
57 onWheel: {
58 if ((!expanded || selected) && scrollAction.valid) {
59 scrollAction.activate(wheel.angleDelta.y > 0 ? stepUp : stepDown);
60 }
61 }
62 }
63
64 Item {
65 id: mainItems
66 anchors.centerIn: parent
67
68 width: leftLabelItem.width + iconsItem.width + rightLabelItem.width
69 implicitHeight: units.gu(2)
70
71 Label {
72 id: leftLabelItem
73 objectName: "leftLabel"
74
75 anchors {
76 left: mainItems.left
77 verticalCenter: parent.verticalCenter
78 }
79 width: contentWidth > 0 ? contentWidth + units.gu(1) : 0
80 horizontalAlignment: Text.AlignHCenter
81
82 opacity: 1.0
83 font.family: "Lomiri"
84 fontSize: "medium"
85 font.weight: Font.Light
86 color: root.color
87 Behavior on color { ColorAnimation { duration: LomiriAnimation.FastDuration; easing: LomiriAnimation.StandardEasing } }
88 }
89
90 Item {
91 id: iconsItem
92 objectName: "icons"
93
94 width: iconRow.width > 0 ? iconRow.width + units.gu(1) : 0
95 anchors {
96 left: leftLabelItem.right
97 verticalCenter: parent.verticalCenter
98 }
99
100 Row {
101 id: iconRow
102 anchors.centerIn: iconsItem
103 spacing: units.gu(1)
104
105 Repeater {
106 id: iconRepeater
107 objectName: "iconRepeater"
108
109 model: d.useFallbackIcon ? [ "image://theme/settings" ] : root.icons
110
111 Icon {
112 id: itemImage
113 objectName: "icon"+index
114 height: iconHeight
115 // FIXME Workaround for bug https://bugs.launchpad.net/lomiri/+source/lomiri-ui-toolkit/+bug/1421293
116 width: implicitWidth > 0 && implicitHeight > 0 ? (implicitWidth / implicitHeight * height) : implicitWidth;
117 source: modelData
118 color: root.color
119 Behavior on color { ColorAnimation { duration: LomiriAnimation.FastDuration; easing: LomiriAnimation.StandardEasing } }
120 }
121 }
122 }
123 }
124
125 Label {
126 id: rightLabelItem
127 objectName: "rightLabel"
128
129 anchors {
130 left: iconsItem.right
131 verticalCenter: parent.verticalCenter
132 }
133 width: contentWidth > 0 ? contentWidth + units.gu(1) : 0
134 horizontalAlignment: Text.AlignHCenter
135
136 opacity: 1.0
137 font.family: "Lomiri"
138 fontSize: "medium"
139 font.weight: Font.Light
140 color: root.color
141 Behavior on color { ColorAnimation { duration: LomiriAnimation.FastDuration; easing: LomiriAnimation.StandardEasing } }
142 }
143 }
144
145 Label {
146 id: indicatorName
147 objectName: "indicatorName"
148
149 anchors.top: mainItems.bottom
150 anchors.topMargin: units.gu(0.5)
151 anchors.horizontalCenter: parent.horizontalCenter
152 width: contentWidth > 0 ? contentWidth + units.gu(1) : 0
153
154 text: identifier
155 fontSize: "x-small"
156 font.weight: Font.Light
157 horizontalAlignment: Text.AlignHCenter
158 opacity: 0
159 color: root.color
160 Behavior on color { ColorAnimation { duration: LomiriAnimation.FastDuration; easing: LomiriAnimation.StandardEasing } }
161 }
162
163 StateGroup {
164 objectName: "indicatorItemState"
165
166 states: [
167 State {
168 name: "minimised"
169 when: !expanded && ((icons && icons.length > 0) || leftLabel !== "" || rightLabel !== "")
170 PropertyChanges { target: indicatorName; opacity: 0}
171 },
172
173 State {
174 name: "minimised_fallback"
175 when: !expanded && (!icons || icons.length === 0) && leftLabel == "" && rightLabel == ""
176 PropertyChanges { target: indicatorName; opacity: 0}
177 PropertyChanges { target: d; useFallbackIcon: true }
178 },
179
180 State {
181 name: "expanded"
182 PropertyChanges { target: indicatorName; visible: true; opacity: 1}
183 PropertyChanges { target: mainItems; anchors.verticalCenterOffset: -units.gu(1) }
184 },
185
186 State {
187 name: "expanded_icon"
188 extend: "expanded"
189 when: expanded && (icons && icons.length > 0)
190 AnchorChanges { target: iconsItem; anchors.left: undefined; anchors.horizontalCenter: parent.horizontalCenter }
191 AnchorChanges { target: leftLabelItem; anchors.left: undefined; anchors.right: iconsItem.left }
192 PropertyChanges { target: leftLabelItem; opacity: 0 }
193 PropertyChanges { target: leftLabelItem; opacity: 0 }
194 PropertyChanges { target: rightLabelItem; opacity: 0 }
195 PropertyChanges { target: root; width: Math.max(units.gu(10), Math.max(iconsItem.width, indicatorName.width)) }
196 },
197
198 State {
199 name: "expanded_fallback"
200 extend: "expanded"
201 when: expanded && (!icons || icons.length === 0) && leftLabel == "" && rightLabel == ""
202 PropertyChanges { target: d; useFallbackIcon: true }
203 AnchorChanges { target: iconsItem; anchors.left: undefined; anchors.horizontalCenter: parent.horizontalCenter }
204 AnchorChanges { target: leftLabelItem; anchors.left: undefined; anchors.right: iconsItem.left }
205 PropertyChanges { target: leftLabelItem; opacity: 0 }
206 PropertyChanges { target: leftLabelItem; opacity: 0 }
207 PropertyChanges { target: rightLabelItem; opacity: 0 }
208 PropertyChanges { target: root; width: Math.max(units.gu(10), Math.max(iconsItem.width, indicatorName.width)) }
209 },
210
211 State {
212 name: "expanded_rightLabel"
213 extend: "expanded"
214 when: expanded && (!icons || icons.length === 0) && rightLabel !== ""
215 AnchorChanges { target: rightLabelItem; anchors.left: undefined; anchors.horizontalCenter: parent.horizontalCenter }
216 PropertyChanges { target: iconsItem; opacity: 0 }
217 PropertyChanges { target: leftLabelItem; opacity: 0 }
218 PropertyChanges { target: root; width: Math.max(units.gu(10), Math.max(rightLabelItem.width, indicatorName.width)) }
219 },
220
221 State {
222 name: "expanded_leftLabel"
223 extend: "expanded"
224 when: expanded && (!icons || icons.length === 0) && leftLabel !== ""
225 AnchorChanges { target: leftLabelItem; anchors.left: undefined; anchors.horizontalCenter: parent.horizontalCenter }
226 PropertyChanges { target: iconsItem; opacity: 0 }
227 PropertyChanges { target: rightLabelItem; opacity: 0 }
228 PropertyChanges { target: root; width: Math.max(units.gu(10), Math.max(leftLabelItem.width, indicatorName.width)) }
229 }
230 ]
231
232 transitions: [
233 Transition {
234 id: stateTransition
235 PropertyAction { target: d; property: "useFallbackIcon" }
236 AnchorAnimation {
237 targets: [ mainItems, iconsItem, leftLabelItem, rightLabelItem ]
238 duration: LomiriAnimation.SnapDuration; easing: LomiriAnimation.StandardEasing
239 }
240 PropertyAnimation {
241 targets: [ root, mainItems, iconsItem, leftLabelItem, rightLabelItem, indicatorName ]
242 properties: "width, opacity, anchors.verticalCenterOffset";
243 duration: LomiriAnimation.SnapDuration; easing: LomiriAnimation.StandardEasing
244 }
245 }
246 ]
247 }
248
249 rootActionState.onUpdated: {
250 if (rootActionState == undefined) {
251 title = "";
252 leftLabel = "";
253 rightLabel = "";
254 icons = undefined;
255 return;
256 }
257
258 title = rootActionState.title ? rootActionState.title : rootActionState.accessibleName;
259 leftLabel = rootActionState.leftLabel ? rootActionState.leftLabel : "";
260 rightLabel = rootActionState.rightLabel ? rootActionState.rightLabel : "";
261 icons = rootActionState.icons;
262 }
263
264 QtObject {
265 id: d
266
267 property bool useFallbackIcon: false
268 property var shouldIndicatorBeShown: undefined
269
270 onShouldIndicatorBeShownChanged: {
271 if (shouldIndicatorBeShown !== undefined) {
272 submenuAction.changeState(shouldIndicatorBeShown);
273 }
274 }
275 }
276
277 AyatanaMenuAction {
278 id: secondaryAction
279 model: menuModel
280 index: 0
281 name: rootActionState.secondaryAction
282 }
283
284 AyatanaMenuAction {
285 id: scrollAction
286 model: menuModel
287 index: 0
288 name: rootActionState.scrollAction
289 }
290
291 AyatanaMenuAction {
292 id: submenuAction
293 model: menuModel
294 index: 0
295 name: rootActionState.submenuAction
296 }
297
298 Binding {
299 target: d
300 property: "shouldIndicatorBeShown"
301 when: submenuAction.valid
302 value: root.selected && root.expanded
303 }
304}