2
* Copyright 2015 Canonical Ltd.
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.
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.
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/>.
18
import Ubuntu.Components 1.3 as Components
23
\inqmlmodule Ubuntu.Components 1.1
26
Components.StyledItem {
36
Animate showing and hiding of the header.
38
property bool animate: true
41
The background color of the divider. Value set by MainView.
43
property color dividerColor
46
The background color of the panel. Value set by MainView.
48
property color panelColor
51
enabled: animate && !(header.flickable && header.flickable.moving)
53
duration: Components.UbuntuAnimation.BriskDuration
59
internal.checkFlickableMargins();
60
internal.movementEnded();
61
if (header.config.visible) {
68
// with PageHeadConfiguration 1.2, always be visible.
69
visible: title || contents || tabsModel || internal.newConfig
71
internal.checkFlickableMargins();
78
if (internal.newConfig) {
79
header.config.visible = true;
88
if (internal.newConfig) {
89
header.config.visible = false;
91
header.y = -header.height;
95
The text to display in the header
97
property string title: ""
99
// deprecated for new versions of PageHeadConfiguration
100
if (!internal.newConfig) {
106
The contents of the header. If this is set, \l title will be ignored.
107
DEPRECATED and replaced by Page.head.contents.
109
property Item contents: null
111
// deprecated for new versions of PageHeadConfiguration
112
if (!internal.newConfig) {
118
A model of tabs to represent in the header.
119
This is automatically set by \l Tabs.
121
property var tabsModel: null
124
If it is possible to pop this PageStack, a back button will be
127
property var pageStack: null
131
\qmlproperty list<Action> actions
132
The list of actions actions that will be shown in the header.
133
DEPRECATED. Use Page.head.actions instead.
136
onActionsChanged: print("WARNING: Header.actions property is DEPRECATED. "+
137
"Use Page.head.actions instead.")
142
Action shown before the title. Setting this will disable the back
143
button and tabs drawer button in the new header and replace it with a button
144
representing the action below.
145
DEPRECATED. Use Page.head.backAction property instead.
147
property var __customBackAction: null
149
// FIXME: Currently autopilot can only get visual items, but once bug #1273956
150
// is fixed to support non-visual items, a QtObject may be used.
151
// --timp - 2014-03-20
153
// FIXME: This is a workaround to be able to get the properties of
154
// tabsModel in an autopilot test.
155
objectName: "tabsModelProperties"
156
property int count: tabsModel ? tabsModel.count : 0
157
property int selectedIndex: tabsModel ? tabsModel.selectedIndex : -1
160
// FIXME: This is a workaround to be able to get the properties of
161
// the sections in an autopilot test.
162
objectName: "sectionsProperties"
163
property int selectedIndex: header.config ? header.config.sections.selectedIndex : -1
167
The flickable that controls the movement of the header.
168
Will be set automatically by Pages inside a MainView, but can
171
property Flickable flickable: null
172
onFlickableChanged: {
173
internal.connectFlickable();
174
if (!internal.newConfig || !header.config.locked) {
182
property bool useDeprecatedToolbar: true
185
Configuration of the header.
186
FIXME: Must be of type PageHeadConfiguration. Setting that as the property type
187
however will use the latest version (1.3) and a Page that uses an older
188
version (1.1) will no longer work.
190
property QtObject config: null
192
// set internal.newConfig because when we rely on the binding,
193
// the value of newConfig may be updated after executing the code below.
194
internal.newConfig = config && config.hasOwnProperty("visible") &&
195
config.hasOwnProperty("locked");
196
internal.connectFlickable();
198
if (internal.newConfig && header.config.locked &&!header.config.visible) {
205
target: header.config
206
ignoreUnknownSignals: true // PageHeadConfiguration <1.2 lacks the signals below
208
if (header.config.visible) {
213
internal.checkFlickableMargins();
216
internal.connectFlickable();
217
if (!header.config.locked) {
218
internal.movementEnded();
224
The header is not fully opened or fully closed.
226
This property is true if the header is animating towards a fully
227
opened or fully closed state, or if the header is moving due to user
228
interaction with the flickable.
230
The value of moving is always false when using an old version of
231
PageHeadConfiguration (which does not have the visible property).
233
Used in tst_header_locked_visible.qml.
235
readonly property bool moving: internal.newConfig &&
236
((config.visible && header.y !== 0) ||
237
(!config.visible && header.y !== -header.height))
242
// This property is updated in header.onConfigChanged to ensure it
243
// is updated before other functions are called in onConfigChanged.
244
property bool newConfig: header.config &&
245
header.config.hasOwnProperty("locked") &&
246
header.config.hasOwnProperty("visible")
249
Track the y-position inside the flickable.
251
property real previousContentY: 0
254
The previous flickable to disconnect events
256
property Flickable previousFlickable: null
259
Disconnect previous flickable, and connect the new one.
261
function connectFlickable() {
262
// Finish the current header movement in case the current
263
// flickable is disconnected while scrolling:
264
internal.movementEnded();
266
if (previousFlickable) {
267
previousFlickable.contentYChanged.disconnect(internal.scrollContents);
268
previousFlickable.movementEnded.disconnect(internal.movementEnded);
269
previousFlickable.interactiveChanged.disconnect(internal.interactiveChanged);
270
previousFlickable = null;
272
if (flickable && !(internal.newConfig && header.config.locked)) {
273
// Connect flicking to movements of the header
274
previousContentY = flickable.contentY;
275
flickable.contentYChanged.connect(internal.scrollContents);
276
flickable.movementEnded.connect(internal.movementEnded);
277
flickable.interactiveChanged.connect(internal.interactiveChanged);
278
flickable.contentHeightChanged.connect(internal.contentHeightChanged);
279
previousFlickable = flickable;
281
internal.checkFlickableMargins();
285
Update the position of the header to scroll with the flickable.
287
function scrollContents() {
288
// Avoid updating header.y when rebounding or being dragged over the bounds.
289
if (!flickable.atYBeginning && !flickable.atYEnd) {
290
var deltaContentY = flickable.contentY - previousContentY;
291
// FIXME: MathUtils.clamp is expensive. Fix clamp, or replace it here.
292
header.y = MathUtils.clamp(header.y - deltaContentY, -header.height, 0);
294
previousContentY = flickable.contentY;
298
Fully show or hide the header, depending on its current y.
300
function movementEnded() {
301
if (!(internal.newConfig && header.config.locked)) {
302
if ( (flickable && flickable.contentY < 0) ||
303
(header.y > -header.height/2)) {
312
Content height of flickable changed
314
function contentHeightChanged() {
315
if (flickable && flickable.height >= flickable.contentHeight) header.show();
319
Flickable became interactive or non-interactive.
321
function interactiveChanged() {
322
if (flickable && !flickable.interactive) header.show();
326
Check the topMargin of the flickable and set it if needed to avoid
327
contents becoming unavailable behind the header.
329
function checkFlickableMargins() {
330
if (header.flickable) {
331
var headerHeight = 0;
332
if (header.visible && !(internal.newConfig &&
333
header.config.locked &&
334
!header.config.visible)) {
335
headerHeight = header.height;
338
if (flickable.topMargin !== headerHeight) {
339
var oldContentY = flickable.contentY;
340
var previousHeaderHeight = flickable.topMargin;
341
flickable.topMargin = headerHeight;
342
// push down contents when header grows,
343
// pull up contents when header shrinks.
344
flickable.contentY = oldContentY - headerHeight + previousHeaderHeight;
350
theme.version: Components.Ubuntu.toolkitVersion
351
styleName: header.useDeprecatedToolbar ? "HeaderStyle" : "PageHeadStyle"