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

KDE's Doxygen guidelines are available online.