MauiKit Controls

Page.qml
1/*
2 * Copyright 2019 Camilo Higuita <milo.h@aol.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20import QtQuick
21import QtQml
22import QtQuick.Controls
23import QtQuick.Layouts
24import Qt5Compat.GraphicalEffects
25
26import org.mauikit.controls 1.3 as Maui
27
28/**
29 * @inherit QtQuick.Controls.Pane
30 * @since org.mauikit.controls 1.0
31 *
32 * @brief A page with a header and footer, that can be flipped among many other features.
33 *
34 * <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-pane.html">This control inherits from QQC2 Pane, to checkout its inherited properties refer to the Qt Docs.</a>
35 *
36 * This page has a header and footer bars that by default are set to a MauiKit ToolBar,
37 * the header bar can be dynamically moved to the bottom under the footer for better
38 * reachability on hand held devices like phones.
39 * @see ToolBar
40 *
41 * Any other item can be placed as the header or footer. And the default toolbars can be populated easily via the aliases:
42 * @see headBar
43 * @see footBar
44 *
45 * @code
46 * Page
47 * {
48 * id: _page
49 *
50 * header: Rectangle
51 * {
52 * width: parent.width
53 * height: 40
54 * color: "pink"
55 * }
56 * }
57 * @endcode
58 *
59 * @image html Page/page_structure.png "A Page with a header and footer - and then the header moved to the bottom under the footer"
60 *
61 * @section features Features
62 *
63 * Among other features, the page can have a reference to a flickable element to allow to have pull-back
64 * toolbar behaviour, floating toolbars, etc.
65 *
66 * @subsection pullback-bars Pull-Back Bars
67 *
68 * Pull-back bars allow to expand the contents areas by pulling away the header or footer when content is being flicked/scrolled - which is useful on phone screens. To enable this behaviour you need to reference the Flickable element via the flickable property.
69 * @see flickable
70 *
71 * And set the header/footer positioning properties to ListView.PullBackHeader. By default this is set to the header if a flickable element has been assigned, so you can disable it by setting the property to ListView.InlineHeader.
72 * @see footerPositioning
73 * @see headerPositioning
74 *
75 * @subsection bars Bars Layout
76 *
77 * As mentioned before, the Page has a header and footer area- the header can be moved to the bottom via the alternate header property. But you can also stack multiple bars vertically. So you can have two or more header/footer bars.
78 * @see altHeader
79 *
80 * To attach more bars use the header and footer columns property.
81 * @see headerColumn
82 * @see footerColumn
83 *
84 * @code
85 * Page
86 * {
87 * id: _page
88 *
89 * headerColumn: [
90 * Rectangle
91 * {
92 * width: parent.width
93 * height: 40
94 * color: "pink"
95 * },
96 *
97 * Rectangle
98 * {
99 * width: parent.width
100 * height: 40
101 * color: "yellow"
102 * }
103 * ]
104 * }
105 * @endcode
106 *
107 * The header/footer layout is handled by a Column control, which can be accessed via the aliases to tweak the spacing for example.
108 * @see headerContainer
109 * @see footerContainer
110 *
111 * @image html Page/headerColumn.png "A Page with a default header bar and two rectangles stacked as part of the header column"
112 *
113 * @subsection floatingbars Floating & AutoHide
114 *
115 * The header and/or footer bars can be set to a floating position - which means they will flow over the page contents at the bottom and top. When this is enable a translucency effect will be applied to hint about the content being covered underneath.
116 * @see floatingFooter
117 * @see floatingHeader
118 *
119 * The bars can also be set to auto-hide, when the cursor moves out or shown again when the cursor enters the bar area.
120 * @see autoHideFooter
121 * @see autoHideHeader
122 *
123 * The time to trigger this actions can be tweaked using the delay properties.
124 * @see autoHideFooterDelay
125 * @see autoHideHeaderDelay
126 *
127 * And to finetune the target area which reacts to enter and exit events, use the margins property:
128 * @see autoHideFooterMargins
129 * @see autoHideHeaderMargins
130 *
131 * @image html Page/floating_header.png "A Page with a floating header - and a translucent effect"
132 *
133 * @section notes Notes
134 * This component is an alternative to the QQC2 Page control, where the header and footer can not be moved easily - and it adds a few more functionality.
135 *
136 * The padding properties will affect the header and footer, so if instead you meant to add internal padding to the page contents, you can use the margins properties.
137 *
138 * When used in a StackView or SwipeView, this Page emits two signals for the go forward/back actions, which can be consumed to pop or push pages.
139 * @see goBackTriggered
140 *
141 * @code
142 * Page
143 * {
144 * id: _page
145 *
146 * headBar.rightContent: Switch
147 * {
148 * text: "Alt Header"
149 * checked: _page.altHeader
150 * onToggled: _page.altHeader = checked
151 * }
152 * }
153 * @endcode
154 *
155 * @image html Page/alt_header_dark.png "An ApplicationWindow filled with a Page and with the CSD controls enabled"
156 *
157 * <a href="https://invent.kde.org/maui/mauikit/-/blob/qt6-2/examples/Page.qml">You can find a more complete example at this link.</a>
158 *
159 * @note This control supports the attached Controls.showCSD property to display the window control buttons when using CSD. This is only supported if used with the MauiKit ToolBar as the header bar - which is the default. If use with another header element, the window control buttons need to be added manually.
160 */
161Pane
162{
163 id: control
164
165 padding: 0
166 leftPadding: control.padding
167 rightPadding: control.padding
168 topPadding: control.padding
169 bottomPadding: control.padding
170
171 Maui.Theme.colorSet: Maui.Theme.View
172 Maui.Theme.inherit: false
173 Maui.Controls.showCSD: false
174 /**
175 * @brief The default content of the page.
176 * To position child elements use anchors or do it manually.
178 * @note This is a `default` property
179 *
180 * @property list<QtObject> Page::content
181 */
182 default property alias content: _content.data
184 /**
185 * @brief An alias to the actual page container.
186 * @property Item Page::pageContent
187 */
188 readonly property alias pageContent : _content
189
190 /**
191 *
192 * The actual height of the page contents without the header or footer bars height.
193 * @property int Page::internalHeight
194 */
195 readonly property alias internalHeight : _content.height
197 /**
198 * @brief A flickable element can be referenced in order to support the header and footer positioning options such as Inline, Pullback or floating.
199 * If a flickable is set, the page will modify its top or bottom margins properties.
200 * And watch for changes in the Flickable properties, such as contentX and contentY in order to support the formerly mentioned features.
201 */
202 property Flickable flickable : null
203
204 /**
205 * @brief The footer bar can be place static and always visible with the InlineFooter value, or moved along with the flickable contents when using the PullBackFooter value.
206 * This is only supported if a flickable element has been set.
207 * @see flickable
208 * By default this is set to InlineFooter.
209 *
210 * Possible values are:
211 * - ListView.PullBackFooter
212 * - ListView.InlineFooter
213 */
214 property int footerPositioning : ListView.InlineFooter
215
216 /**
217 * @brief The header bar can be place static and always visible with the InlineHeader value, or moved along with the flickable contents when using the PullBackHeader value.
218 * This is only supported if a flickable element has been set.
219 * @see flickable
220 *
221 * By default this is set to `InlineHeader` unless a Flickable has been attached, in which case it is set to `PullBackHeader`.
222 *
223 * Possible values are:
224 * - ListView.PullBackHeader
225 * - ListView.InlineHeader
226 */
227 property int headerPositioning : flickable ? ListView.PullBackHeader : ListView.InlineHeader
228
230 /**
231 * @brief Convinient way to change the color set of the default header.
232 * @code
233 * Page
234 * {
235 * headerColorSet: Theme.Complementary
236 * }
237 * @endcode
238 */
239 property int headerColorSet : altHeader ? Maui.Theme.Window : Maui.Theme.Header
241 /**
242 * @brief A title for the page.
243 * This title is shown in the middle of the default header bar if the show title property is set to true.
244 * @see showTitle
245 * The displayed title in the header bar won't wrap, but will elide in the middle.
246 */
247 property string title
248
249 /**
250 * @brief If a title is set and this is set to true, such title will be displayed in the default header bar in the middle.
251 */
252 property bool showTitle : true
254 /**
255 * @brief An alias to the default ToolBar as the header bar.
256 * The toolbar is a MauiKit ToolBar.
257 * @see ToolBar
258 * @property ToolBar Page::headBar
259 */
260 property alias headBar : _headBar
261
262 /**
263 * @brief An alias to the default ToolBar as the footer bar.
264 * The toolbar is a MauiKit ToolBar.
265 * @property ToolBar Page::footBar
266 */
267 property alias footBar: _footBar
268
269 /**
270 * @brief Quick way to add more children to the footer bar.
271 * The footer bar is handled by a Column.
272 * @property list<QtObject> Page::footerColumn
273 */
274 property alias footerColumn : _footerContent.data
276 /**
277 * @brief The actual container for all the footer bars.
278 * @property Column Page::footerContainer
279 */
280 property alias footerContainer : _footerContent
282 /**
283 * @brief Quick way to add more children to the header bar.
284 * The header bar is handled by a Colum.
285 * @property list<QtObject> Page::headerColumn
286 */
287 property alias headerColumn : _headerContent.data
288
289 /**
290 * @brief The actual container for all the header bars.
291 * @property Column Page::headerContainer
292 */
293 property alias headerContainer : _headerContent
294
295 /**
296 * @brief The page margins for the page contents.
297 * This margins do not affect the header or footer bars.
298 * By default this is set to 0
299 */
300 property int margins: 0
301
302 /**
303 * @brief Page left margins
304 */
305 property int leftMargin : margins
306
307 /**
308 * @brief Page right margins
309 */
310 property int rightMargin: margins
311
312 /**
313 * @brief Page top margins
314 */
315 property int topMargin: margins
316
317 /**
318 * @brief Page bottom margins
319 */
320 property int bottomMargin: margins
321
322 /**
323 * @brief If set to `true` the header bar will be positioned to the bottom under the footer bar.
324 * This makes sense in some cases for better reachability, or custom design patterns.
325 */
326 property bool altHeader : false
328 /**
329 * @brief If the header bar should autohide under certain given condition.
330 * To fine tune a enter/exit threshold, a margin can be set, and a time delay.
331 */
332 property bool autoHideHeader : false
333
334 /**
335 * @brief If the footer bar should autohide under certain given condition.
336 * To fine tune a enter/exit threshold, a margin can be set, and a time delay.
337 */
338 property bool autoHideFooter : false
339
340 /**
341 * @brief Size in pixels for the cursor enter/exit threshold for when the header should autohide.
342 * The default value is set to `Style.toolBarHeight`.
343 */
344 property int autoHideHeaderMargins : Maui.Style.toolBarHeight
346 /**
347 * @brief Size in pixels for the cursor enter/exit threshold for when the footer should autohide.
348 * The default value is set to `Style.toolBarHeight`.
349 */
350 property int autoHideFooterMargins : Maui.Style.toolBarHeight
351
352 /**
353 * @brief Span of time to hide the footer bar after the conditions have been met.
354 * If within the span of time the conditions changed then the timer gets reseted.
355 */
356 property int autoHideFooterDelay : Maui.Handy.isTouch ? 0 : 1000
357
358 /**
359 * @brief Span of time to hide the header bar after the conditions have been met.
360 * If within the span of time the conditions changed then the timer gets reseted.
361 */
362 property int autoHideHeaderDelay : Maui.Handy.isTouch ? 0 : 1000
363
364
365 /**
366 * @brief If the header bar should float over the page contents, if set- then the default footer bar will have a translucent `ShaderEffect` to hint about the content under it.
367 */
368 property bool floatingHeader : false
369
370 /**
371 * @brief If the footer bar should float over the page contents, if a flickable has been set then the default footer bar will have a translucent `ShaderEffect`
372 * to hint about the content under it.
373 */
374 property bool floatingFooter: false
375
376 /**
377 * @brief Emitted when the user has requested to go back by a gesture or keyboard shortcut.
378 */
379 signal goBackTriggered()
380
381 /**
382 * @brief Emitted when the user has requested to go forward by a gesture or keyboard shortcut.
383 */
384 signal goForwardTriggered()
385
386 QtObject
387 {
388 id: _private
389 property int topMargin : (!control.altHeader ? (control.floatingHeader ? 0 : _headerContent.implicitHeight) : 0) + control.topMargin
390 property int bottomMargin: ((control.floatingFooter && control.footerPositioning === ListView.InlineFooter ? 0 : _footerContent.implicitHeight) + (control.altHeader ? _headerContent.implicitHeight : 0))
391 }
392
393 background: Rectangle
394 {
395 color: Maui.Theme.backgroundColor
396 Behavior on color
397 {
398 Maui.ColorTransition{}
399 }
400 }
401
402 onFlickableChanged:
403 {
404 returnToBounds()
405 }
406
407 Binding
408 {
409 when: control.floatingFooter && control.footerPositioning === ListView.InlineFooter && _footerContent.implicitHeight > 0
410 target: control.flickable
411 property: "bottomMargin"
412 value: _footerContent.implicitHeight
413 restoreMode: Binding.RestoreBindingOrValue
414 }
415
416 Connections
417 {
418 target: control.flickable ? control.flickable : null
419 ignoreUnknownSignals: true
420 enabled: control.flickable && ((control.header && control.headerPositioning === ListView.PullBackHeader) || (control.footer && control.footerPositioning === ListView.PullBackFooter))
421 property int oldContentY
422 property bool updatingContentY: false
423
424 function onContentYChanged()
425 {
426 _headerAnimation.enabled = false
427 _footerAnimation.enabled = false
428
429 if(!control.flickable.dragging && control.flickable.atYBeginning)
430 {
431 control.returnToBounds()
432 }
433
434 if (updatingContentY || !control.flickable || !control.flickable.dragging)
435 {
436 oldContentY = control.flickable.contentY;
437 return;
438 //TODO: merge
439 //if moves but not dragging, just update oldContentY
440 }
441
442 if(control.flickable.contentHeight < control.height)
443 {
444 return
445 }
446
447 var oldFHeight
448 var oldHHeight
449
450 if (control.footer && control.footerPositioning === ListView.PullBackFooter && control.footer.visible)
451 {
452 oldFHeight = control.footer.height
453 control.footer.height = Math.max(0,
454 Math.min(control.footer.implicitHeight,
455 control.footer.height + oldContentY - control.flickable.contentY));
456 }
457
458 if (control.header && control.headerPositioning === ListView.PullBackHeader && control.header.visible && !control.altHeader)
459 {
460 oldHHeight = control.header.height
461 control.header.height = Math.max(0,
462 Math.min(control.header.implicitHeight,
463 control.header.height + oldContentY - control.flickable.contentY));
464 }
465
466 //if the implicitHeight is changed, use that to simulate scroll
467 if (control.header && oldHHeight !== control.header.height && control.header.visible && !control.altHeader)
468 {
469 updatingContentY = true
470 control.flickable.contentY -= (oldHHeight - control.header.height)
471 updatingContentY = false
472
473 } else {
474 oldContentY = control.flickable.contentY
475 }
476 }
477
478 function onMovementEnded()
479 {
480 if (control.header && control.header.visible && control.headerPositioning === ListView.PullBackHeader && !control.altHeader)
481 {
482 _headerAnimation.enabled = true
483
484 if (control.header.height >= (control.header.implicitHeight/2) || control.flickable.atYBeginning )
485 {
486 control.header.height = control.header.implicitHeight
487
488 } else
489 {
490 control.header.height = 0
491 }
492 }
493
494 if (control.footer && control.footer.visible && control.footerPositioning === ListView.PullBackFooter)
495 {
496 _footerAnimation.enabled = true
497
498 if (control.footer.height >= (control.footer.implicitHeight/2) || control.flickable.atYEnd)
499 {
500 if(control.flickable.atYEnd)
501 {
502 control.footer.height = control.footer.implicitHeight
503
504 control.flickable.contentY = control.flickable.contentHeight - control.flickable.height
505 oldContentY = control.flickable.contentY
506 }else
507 {
508 control.footer.height = control.footer.implicitHeight
509
510 }
511
512 } else
513 {
514 control.footer.height = 0
515 }
516 }
517 }
518 }
519
520 /**
521 * @brief The main single header bar.
522 * By default this header is set to a MauiKit ToolBar, but it can be changed to any other item.
523 * @see ToolBar
524 */
525 property Item header : Maui.ToolBar
526 {
527 id: _headBar
528 visible: count > 0
529 width: visible ? _headerContent.width : 0
530 position: control.altHeader ? ToolBar.Footer : ToolBar.Header
531 Maui.Controls.showCSD: control.Maui.Controls.showCSD && control.Maui.Controls.showCSD === true && !control.altHeader
532 translucencySource: ShaderEffectSource
533 {
534 sourceItem: _content
535 sourceRect: _headBar.background ? (control.floatingHeader ? Qt.rect(0, (_headBar.position === ToolBar.Header ? 0 : _content.height - _headBar.background.height), _headBar.background.width, _headBar.background.height) : Qt.rect(0, (_headBar.position === ToolBar.Header ? 0 - (_headBar.background.height) : _content.height), _headBar.background.width, _headBar.background.height)) : null
536 }
537
538 Binding on height
539 {
540 value: visible ? _headBar.implicitHeight : 0
541 restoreMode: Binding.RestoreBindingOrValue
542 }
543
544 Behavior on height
545 {
546 id: _headerAnimation
547 enabled: false
548 NumberAnimation
549 {
550 duration: Maui.Style.units.shortDuration
551 easing.type: Easing.InOutQuad
552 }
553 }
554
555 Component
556 {
557 id: _titleComponent
558
559 Item
560 {
561 implicitHeight:_titleLabel.implicitHeight
562
563 Label
564 {
565 id: _titleLabel
566 anchors.fill: parent
567 text: control.title
568 elide : Text.ElideRight
569 font: Maui.Style.h2Font
570 horizontalAlignment : Text.AlignHCenter
571 verticalAlignment : Text.AlignVCenter
572 }
573 }
574 }
575
576 middleContent: Loader
577 {
578 visible: item
579 active: control.title && control.showTitle
580 sourceComponent: _titleComponent
581
582 asynchronous: true
583
584 Layout.fillWidth: true
585 Layout.fillHeight: true
586 }
587 }
588
589 //Label
590 //{
591 //z: 999999999999
592 //color: "yellow"
593 //text: _footBar.visibleCount + " / " + _footBar.count + " - " + _footBar.height + " / " + footer.height + " - " + _footBar.visible + " / " + footer.visible + " / " + footer.height + " / " + _footerContent.implicitHeight + " / " + _footerContent.implicitHeight
594 //}
595
596 /**
597 * @brief The main single footer bar.
598 * By default this footer is set to a MauiKit ToolBar, but it can be changed to any other item.
599 * @see ToolBar
600 */
601 property Item footer : Maui.ToolBar
602 {
603 id: _footBar
604 visible: count > 0
605 width: visible ? _footerContent.width : 0
606 height: visible ? implicitHeight : 0
607
608 position: ToolBar.Footer
609
610 translucencySource: ShaderEffectSource
611 {
612 //textureSize: Qt.size(_headBarBG.width * 0.2, _headBarBG.height * 0.2)
613 sourceItem: _content
614 sourceRect: _footBar.background ? (control.floatingFooter ? Qt.rect(0, _content.height - _footBar.background.height, _footBar.background.width, _footBar.background.height) : Qt.rect(0, _content.height, _footBar.background.width, _footBar.background.height)) : Qt.rect()
615 }
616
617 Behavior on height
618 {
619 id: _footerAnimation
620 enabled: false
621 NumberAnimation
622 {
623 duration: Maui.Style.units.shortDuration
624 easing.type: Easing.InOutQuad
625 }
626 }
627 }
628
629 states: [ State
630 {
631 when: !altHeader
632
633 AnchorChanges
634 {
635 target: _headerContent
636 anchors.top: parent.top
637 anchors.bottom: undefined
638 }
639
640 AnchorChanges
641 {
642 target: _footerContent
643 anchors.top: undefined
644 anchors.bottom: parent.bottom
645 }
646 },
647
648 State
649 {
650 when: altHeader
651
652 AnchorChanges
653 {
654 target: _headerContent
655 anchors.top: undefined
656 anchors.bottom: parent.bottom
657 }
658
659 AnchorChanges
660 {
661 target: _footerContent
662 anchors.top: undefined
663 anchors.bottom: _headerContent.top
664 }
665 } ]
666
667 onAutoHideHeaderChanged:
668 {
669 if(control.autoHideHeader)
670 {
671 pullBackHeader()
672 }else
673 {
674 pullDownHeader()
675 }
676 }
677
678 onAutoHideFooterChanged:
679 {
680 if(control.autoHideFooter)
681 {
682 pullBackFooter()
683 } else
684 {
685 pullDownFooter()
686 }
687 }
688 onAltHeaderChanged: pullDownHeader()
689
690
691 // Label
692 // {
693 // anchors.centerIn: _headerContent
694 // text: header.height + "/" + _headerContent.height + " - " + _layout.anchors.topMargin
695 // color: "orange"
696 // z: _headerContent.z + 1
697 // visible: header.visible
698 // }
699 //
700 // Label
701 // {
702 // anchors.centerIn: _footerContent
703 // text: footer.height + "/" + _footerContent.height + " - " + _layout.anchors.topMargin
704 // color: "orange"
705 // z: _footerContent.z + 9999
706 // }
707
708 contentItem: Item
709 {
710 Item
711 {
712 id: _content
713 anchors.fill: parent
714
715 anchors.topMargin: _private.topMargin
716 anchors.bottomMargin: _private.bottomMargin
717
718 anchors.leftMargin: control.leftMargin
719 anchors.rightMargin: control.rightMargin
720 }
721
722 Loader
723 {
724 active: control.Maui.Controls.showCSD === true && control.altHeader
725 asynchronous: true
726 width: parent.width
727
728 sourceComponent: Maui.ToolBar
729 {
730 anchors.top: parent.top
731 Maui.Controls.showCSD: true
732 background: Rectangle
733 {
734 Maui.Theme.colorSet: control.Maui.Theme.colorSet
735 Maui.Theme.inherit: false
736 opacity: 0.8
737 scale: -1 //for mirroring
738 gradient: Gradient {
739 orientation: Gradient.Horizontal
740 GradientStop { position: 0.0; color: Maui.Theme.backgroundColor }
741 GradientStop { position: 0.33; color: "transparent" }
742 GradientStop { position: 1.0; color: "transparent" }
743 }
744 }
745 }
746 }
747
748 Column
749 {
750 id: _headerContent
751 anchors.left: parent.left
752 anchors.right: parent.right
753 }
754
755 Column
756 {
757 id: _footerContent
758 anchors.left: parent.left
759 anchors.right: parent.right
760 }
761
762 Loader
763 {
764 anchors.fill: parent
765 asynchronous: true
766 sourceComponent: MouseArea // to support tbutton go back and forward
767 {
768 propagateComposedEvents: true
769 acceptedButtons: Qt.BackButton | Qt.ForwardButton
770 cursorShape: undefined
771
772 onPressed: (mouse) =>
773 {
774 mouse.accepted = false
775 if(mouse.button === Qt.BackButton)
776 {
777 control.goBackTriggered()
778 }
779
780 if(mouse.button === Qt.ForwardButton)
781 {
782 control.goForwardTriggered()
783 }
784 }
785 }
786 }
787
788 Loader
789 {
790 anchors.fill: parent
791 asynchronous: true
792 z: _content.z +1
793 active: (control.autoHideFooter || control.autoHideHeader ) && Maui.Handy.isTouch
794
795 sourceComponent: MouseArea
796 {
797 parent: _content
798 propagateComposedEvents: true
799 drag.filterChildren: true
800
801 Timer
802 {
803 id: doubleClickTimer
804 interval: 900
805 onTriggered:
806 {
807 if(control.autoHideHeader)
808 {
809 if(header.height !== 0)
810 {
811 _autoHideHeaderTimer.start()
812 _revealHeaderTimer.stop()
813
814 }else
815 {
816 _autoHideHeaderTimer.stop()
817 _revealHeaderTimer.start()
818 }
819 }
820
821 if(control.autoHideFooter)
822 {
823 if(footer.height !== 0)
824 {
825 _autoHideFooterTimer.start()
826
827 }else
828 {
829 pullDownFooter()
830 _autoHideFooterTimer.stop()
831 }
832 }
833 }
834 }
835
836 onPressed: (mouse) =>
837 {
838 doubleClickTimer.restart();
839 mouse.accepted = false
840 }
841 }
842 }
843
844 Loader
845 {
846 asynchronous: true
847 anchors.top: parent.top
848 anchors.left: parent.left
849 anchors.right: parent.right
850 height: active ? _headerContent.implicitHeight + control.autoHideHeaderMargins : 0
851 z: _content.z +1
852 active: control.autoHideHeader && !control.altHeader && !Maui.Handy.isTouch
853
854 sourceComponent: Item
855 {
856 HoverHandler
857 {
858 target: parent
859 acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
860
861 onHoveredChanged:
862 {
863 if(!control.autoHideHeader || control.altHeader)
864 {
865 _autoHideHeaderTimer.stop()
866 return
867 }
868
869 if(!hovered)
870 {
871 _autoHideHeaderTimer.start()
872 _revealHeaderTimer.stop()
873
874 }else
875 {
876 _autoHideHeaderTimer.stop()
877 _revealHeaderTimer.start()
878 }
879 }
880 }
881 }
882 }
883
884 Loader
885 {
886 asynchronous: true
887 anchors.bottom: parent.bottom
888 anchors.left: parent.left
889 anchors.right: parent.right
890 height: active ? _footerContent.implicitHeight + control.autoHideFooterMargins : 0
891 z: _footerContent.z - 1
892 active: control.autoHideFooter && !control.altHeader && !Maui.Handy.isTouch
893
894 sourceComponent: Item
895 {
896 HoverHandler
897 {
898 target: parent
899
900 acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
901
902 onHoveredChanged:
903 {
904 if(!control.autoHideFooter)
905 {
906 return
907 }
908
909 if(!hovered)
910 {
911 _autoHideFooterTimer.start()
912
913 }else
914 {
915 pullDownFooter()
916 _autoHideFooterTimer.stop()
917 }
918 }
919 }
920 }
921 }
922 }
923
924 Timer
925 {
926 id: _revealHeaderTimer
927 interval: autoHideHeaderDelay
928
929 onTriggered:
930 {
931 pullDownHeader()
932 }
933 }
934
935 Timer
936 {
937 id: _autoHideHeaderTimer
938 interval: autoHideHeaderDelay
939 onTriggered:
940 {
941 if(control.autoHideHeader)
942 {
943 pullBackHeader()
944 }
945
946 stop()
947 }
948 }
949
950 Timer
951 {
952 id: _autoHideFooterTimer
953 interval: control.autoHideFooterDelay
954 onTriggered:
955 {
956 if(control.autoHideFooter)
957 {
958 pullBackFooter()
959 }
960
961 stop()
962 }
963 }
964
965 //Keys.onBackPressed:
966 //{
967 //control.goBackTriggered();
968 //}
969
970 //Shortcut
971 //{
972 //sequence: "Forward"
973 //onActivated: control.goForwardTriggered();
974 //}
975
976 //Shortcut
977 //{
978 //sequence: StandardKey.Forward
979 //onActivated: control.goForwardTriggered();
980 //}
981
982 //Shortcut
983 //{
984 //sequence: StandardKey.Back
985 //onActivated: control.goBackTriggered();
986 //}
987
988
989 Component.onCompleted :
990 {
991 if(footer)
992 {
993 _footerContent.data.push(footer)
994 }
995
996 if(header)
997 {
998 let data = [header]
999
1000 for(var i in _headerContent.data)
1001 {
1002 data.push(_headerContent.data[i])
1003 }
1004 _headerContent.data = data
1005 }
1006 }
1007
1008 /**
1009 * @brief If the header or footer are hidden, invoking this method will make them show again
1010 */
1011 function returnToBounds()
1012 {
1013 if(control.header)
1014 {
1015 // pullDownHeader()
1016 }
1017
1018 if(control.footer)
1019 {
1020 // pullDownFooter()
1021 }
1022 }
1023
1024 /**
1025 * @brief Forces the header to be hidden by pulling it back
1026 */
1027 function pullBackHeader()
1028 {
1029 _headerAnimation.enabled = true
1030 header.height = 0
1031 }
1032
1033 /**
1034 * @brief Forces the header to be shown by pulling it back in place
1035 */
1036 function pullDownHeader()
1037 {
1038 _headerAnimation.enabled = true
1039 header.height = header.implicitHeight
1040 }
1041
1042 /**
1043 * @brief Forces the footer to be hidden by pulling it back
1044 */
1045 function pullBackFooter()
1046 {
1047 _footerAnimation.enabled = true
1048 footer.height= 0
1049 }
1050
1051 /**
1052 * @brief Forces the footer to be shown by pulling it back in place
1053 */
1054 function pullDownFooter()
1055 {
1056 _footerAnimation.enabled = true
1057 footer.height = _footerContent.implicitHeight
1058 }
1059}
An alternative to QQC2 ToolBar, with a custom horizontal layout - divided into three main sections - ...
Definition ToolBar.qml:115
void stop(Ekos::AlignState mode)
AKONADI_MIME_EXPORT const char Header[]
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:47:05 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.