Warning, /maui/mauikit/src/controls.6/Page.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *   Copyright 2019 Camilo Higuita <milo.h@aol.com>
0003  *
0004  *   This program is free software; you can redistribute it and/or modify
0005  *   it under the terms of the GNU Library General Public License as
0006  *   published by the Free Software Foundation; either version 2, or
0007  *   (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *   GNU General Public License for more details
0013  *
0014  *   You should have received a copy of the GNU Library General Public
0015  *   License along with this program; if not, write to the
0016  *   Free Software Foundation, Inc.,
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0018  */
0019 
0020 import QtQuick
0021 import QtQml
0022 import QtQuick.Controls
0023 import QtQuick.Layouts
0024 import Qt5Compat.GraphicalEffects
0025 
0026 import org.mauikit.controls 1.3 as Maui
0027 
0028 /**
0029  * @inherit QtQuick.Controls.Pane
0030  *  @since org.mauikit.controls 1.0
0031  * 
0032  *  @brief A page with a header and footer, that can be flipped among many other features.
0033  *  
0034  * <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>
0035  * 
0036  *  This page has a header and footer bars that by default are set to a MauiKit ToolBar,
0037  *  the header bar can be dynamically moved to the bottom under the footer for better
0038  *  reachability on hand held devices like phones.
0039  *  @see ToolBar
0040  * 
0041  *  Any other item can be placed as the header or footer. And the default toolbars can be populated easily via the aliases:
0042  *  @see headBar 
0043  *  @see footBar
0044  *  
0045  *  @code
0046  *    Page
0047  *    {
0048  *        id: _page
0049  * 
0050  *        header: Rectangle
0051  *        {
0052  *            width: parent.width
0053  *            height: 40
0054  *            color: "pink"
0055  *        }
0056  *    }
0057  * @endcode  
0058  * 
0059  * @image html Page/page_structure.png "A Page with a header and footer - and then the header moved to the bottom under the footer"
0060  *      
0061  * @section features Features 
0062  *  
0063  * Among other features, the page can have a reference to a flickable element to allow to have pull-back
0064  *  toolbar behaviour, floating toolbars, etc.
0065  *  
0066  * @subsection pullback-bars Pull-Back Bars
0067  *  
0068  * 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. 
0069  * @see flickable
0070  *  
0071  * 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.
0072  * @see footerPositioning 
0073  * @see headerPositioning
0074  *  
0075  * @subsection bars Bars Layout
0076  *  
0077  * 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.
0078  * @see altHeader
0079  *  
0080  * To attach more bars use the header and footer columns property.
0081  * @see headerColumn 
0082  * @see footerColumn 
0083  *   
0084  * @code
0085  *    Page
0086  *    {
0087  *        id: _page
0088  * 
0089  *        headerColumn: [
0090  *            Rectangle
0091  *            {
0092  *                width: parent.width
0093  *                height: 40
0094  *                color: "pink"
0095  *            },
0096  *            
0097  *            Rectangle
0098  *            {
0099  *                width: parent.width
0100  *                height: 40
0101  *                color: "yellow"
0102  *            } 
0103  *        ]
0104  *    }
0105  * @endcode 
0106  * 
0107  * The header/footer layout is handled by a Column control, which can be accessed via the aliases to tweak the spacing for example.
0108  * @see headerContainer
0109  * @see footerContainer
0110  * 
0111  * @image html Page/headerColumn.png "A Page with a default header bar and two rectangles stacked as part of the header column"
0112  *  
0113  * @subsection floatingbars Floating & AutoHide
0114  * 
0115  * 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.
0116  * @see floatingFooter
0117  * @see floatingHeader
0118  * 
0119  * The bars can also be set to auto-hide, when the cursor moves out or shown again when the cursor enters the bar area.
0120  * @see autoHideFooter
0121  * @see autoHideHeader
0122  * 
0123  * The time to trigger this actions can be tweaked using the delay properties.
0124  * @see autoHideFooterDelay 
0125  * @see autoHideHeaderDelay
0126  * 
0127  * And to finetune the target area which reacts to enter and exit events, use the margins property:
0128  * @see autoHideFooterMargins 
0129  * @see autoHideHeaderMargins
0130  * 
0131  * @image html Page/floating_header.png "A Page with a floating header - and a translucent effect"
0132  * 
0133  * @section notes Notes
0134  * 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.
0135  * 
0136  * 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. 
0137  * 
0138  * 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.
0139  * @see goBackTriggered
0140  * 
0141  * @code
0142  *    Page
0143  *    {
0144  *        id: _page
0145  * 
0146  *        headBar.rightContent: Switch
0147  *        {
0148  *            text: "Alt Header"
0149  *            checked: _page.altHeader
0150  *            onToggled: _page.altHeader = checked
0151  *        }
0152  *    }
0153  * @endcode
0154  * 
0155  * @image html Page/alt_header_dark.png "An ApplicationWindow filled with a Page and with the CSD controls enabled"
0156  * 
0157  * <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>
0158  * 
0159  * @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.
0160  */
0161 Pane
0162 {
0163     id: control
0164     
0165     padding: 0
0166     leftPadding: control.padding
0167     rightPadding: control.padding
0168     topPadding: control.padding
0169     bottomPadding: control.padding
0170     
0171     Maui.Theme.colorSet: Maui.Theme.View
0172     Maui.Theme.inherit: false
0173     Maui.Controls.showCSD: false
0174     /**
0175      * @brief The default content of the page.
0176      * To position child elements use anchors or do it manually.
0177      *
0178      * @note This is a `default` property
0179      *
0180      * @property list<QtObject> Page::content
0181      */
0182     default property alias content: _content.data
0183         
0184         /**
0185          * @brief An alias to the actual page container.
0186          * @property Item Page::pageContent
0187          */    
0188         readonly property alias pageContent : _content
0189         
0190         /**
0191          * 
0192          * The actual height of the page contents without the header or footer bars height.
0193          * @property int Page::internalHeight
0194          */         
0195         readonly property alias internalHeight : _content.height
0196         
0197         /**
0198          * @brief A flickable element can be referenced in order to support the header and footer positioning options such as Inline, Pullback or floating.
0199          * If a flickable is set, the page will modify its top or bottom margins properties.
0200          * And watch for changes in the Flickable properties, such as contentX and contentY in order to support the formerly mentioned features.
0201          */
0202         property Flickable flickable : null
0203         
0204         /**
0205          * @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.
0206          * This is only supported if a flickable element has been set.
0207          * @see flickable
0208          * By default this is set to InlineFooter.
0209          * 
0210          * Possible values are:
0211          * - ListView.PullBackFooter
0212          * - ListView.InlineFooter
0213          */
0214         property int footerPositioning : ListView.InlineFooter
0215         
0216         /**
0217          * @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.
0218          * This is only supported if a flickable element has been set.
0219          * @see flickable
0220          * 
0221          * By default this is set to `InlineHeader` unless a Flickable has been attached, in which case it is set to `PullBackHeader`.
0222          * 
0223          * Possible values are:
0224          * - ListView.PullBackHeader
0225          * - ListView.InlineHeader
0226          */
0227         property int headerPositioning : flickable ? ListView.PullBackHeader : ListView.InlineHeader
0228         
0229         
0230         /**
0231          * @brief Convinient way to change the color set of the default header.
0232          * @code
0233          * Page
0234          * { 
0235          *  headerColorSet: Theme.Complementary 
0236          * }
0237          * @endcode
0238          */
0239         property int headerColorSet : altHeader ? Maui.Theme.Window : Maui.Theme.Header
0240         
0241         /**
0242          * @brief A title for the page.
0243          * This title is shown in the middle of the default header bar if the show title property is set to true.
0244          * @see showTitle
0245          * The displayed title in the header bar won't wrap, but will elide in the middle.
0246          */
0247         property string title
0248         
0249         /**
0250          * @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.
0251          */
0252         property bool showTitle : true
0253         
0254         /**
0255          * @brief An alias to the default ToolBar as the header bar.
0256          * The toolbar is a MauiKit ToolBar.
0257          * @see ToolBar
0258          * @property ToolBar Page::headBar
0259          */
0260         property alias headBar : _headBar
0261         
0262         /**
0263          * @brief An alias to the default ToolBar as the footer bar.
0264          * The toolbar is a MauiKit ToolBar.
0265          * @property ToolBar Page::footBar
0266          */
0267         property alias footBar: _footBar
0268         
0269         /**
0270          * @brief Quick way to add more children to the footer bar.
0271          * The footer bar is handled by a Column.
0272          * @property list<QtObject> Page::footerColumn
0273          */
0274         property alias footerColumn : _footerContent.data
0275         
0276         /**
0277          * @brief The actual container for all the footer bars.
0278          * @property Column Page::footerContainer
0279          */
0280         property alias footerContainer : _footerContent
0281         
0282         /**
0283          * @brief Quick way to add more children to the header bar.
0284          * The header bar is handled by a Colum.
0285          * @property list<QtObject> Page::headerColumn
0286          */
0287         property alias headerColumn : _headerContent.data
0288         
0289         /**
0290          * @brief The actual container for all the header bars.
0291          * @property Column Page::headerContainer
0292          */
0293         property alias headerContainer : _headerContent
0294         
0295         /**
0296          * @brief The page margins for the page contents.
0297          * This margins do not affect the header or footer bars.
0298          * By default this is set to 0
0299          */
0300         property int margins: 0
0301         
0302         /**
0303          * @brief Page left margins
0304          */
0305         property int leftMargin : margins
0306         
0307         /**
0308          * @brief Page right margins
0309          */
0310         property int rightMargin: margins
0311         
0312         /**
0313          * @brief Page top margins
0314          */
0315         property int topMargin: margins
0316         
0317         /**
0318          * @brief Page bottom margins
0319          */
0320         property int bottomMargin: margins
0321         
0322         /**
0323          * @brief If set to `true` the header bar will be positioned to the bottom under the footer bar.
0324          * This makes sense in some cases for better reachability, or custom design patterns.
0325          */
0326         property bool altHeader : false
0327         
0328         /**
0329          * @brief If the header bar should autohide under certain given condition.
0330          * To fine tune a enter/exit threshold, a margin can be set, and a time delay.
0331          */
0332         property bool autoHideHeader : false
0333         
0334         /**
0335          * @brief If the footer bar should autohide under certain given condition.
0336          * To fine tune a enter/exit threshold, a margin can be set, and a time delay.
0337          */
0338         property bool autoHideFooter : false
0339         
0340         /**
0341          * @brief Size in pixels for the cursor enter/exit threshold for when the header should autohide.
0342          * The default value is set to `Style.toolBarHeight`.
0343          */
0344         property int autoHideHeaderMargins : Maui.Style.toolBarHeight
0345         
0346         /**
0347          * @brief Size in pixels for the cursor enter/exit threshold for when the footer should autohide.
0348          * The default value is set to `Style.toolBarHeight`.
0349          */
0350         property int autoHideFooterMargins : Maui.Style.toolBarHeight
0351         
0352         /**
0353          * @brief Span of time to hide the footer bar after the conditions have been met.
0354          * If within the span of time the conditions changed then the timer gets reseted.
0355          */
0356         property int autoHideFooterDelay : Maui.Handy.isTouch ? 0 : 1000
0357         
0358         /**
0359          * @brief Span of time to hide the header bar after the conditions have been met.
0360          * If within the span of time the conditions changed then the timer gets reseted.
0361          */
0362         property int autoHideHeaderDelay : Maui.Handy.isTouch ? 0 : 1000
0363         
0364         
0365         /**
0366          * @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.
0367          */
0368         property bool floatingHeader : false
0369         
0370         /**
0371          * @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`
0372          * to hint about the content under it.
0373          */
0374         property bool floatingFooter: false
0375         
0376         /**
0377          * @brief Emitted when the user has requested to go back by a gesture or keyboard shortcut.
0378          */
0379         signal goBackTriggered()
0380         
0381         /**
0382          * @brief Emitted when the user has requested to go forward by a gesture or keyboard shortcut.
0383          */
0384         signal goForwardTriggered()
0385         
0386         QtObject
0387         {
0388             id: _private
0389             property int topMargin : (!control.altHeader ? (control.floatingHeader ? 0 : _headerContent.implicitHeight) : 0) + control.topMargin
0390             property int bottomMargin: ((control.floatingFooter && control.footerPositioning === ListView.InlineFooter ? 0 : _footerContent.implicitHeight)  + (control.altHeader ? _headerContent.implicitHeight : 0))
0391         }
0392         
0393         background: Rectangle
0394         {
0395             color: Maui.Theme.backgroundColor
0396             Behavior on color
0397             {
0398                 Maui.ColorTransition{}
0399             }
0400         }
0401         
0402         onFlickableChanged:
0403         {
0404             returnToBounds()
0405         }
0406         
0407         Binding
0408         {
0409             when:  control.floatingFooter && control.footerPositioning === ListView.InlineFooter && _footerContent.implicitHeight > 0
0410             target: control.flickable
0411             property: "bottomMargin"
0412             value: _footerContent.implicitHeight
0413             restoreMode: Binding.RestoreBindingOrValue
0414         }
0415         
0416         Connections
0417         {
0418             target: control.flickable ? control.flickable : null
0419             ignoreUnknownSignals: true
0420             enabled: control.flickable && ((control.header && control.headerPositioning === ListView.PullBackHeader) || (control.footer &&  control.footerPositioning === ListView.PullBackFooter))
0421             property int oldContentY
0422             property bool updatingContentY: false
0423             
0424             function onContentYChanged()
0425             {
0426                 _headerAnimation.enabled = false
0427                 _footerAnimation.enabled = false
0428                 
0429                 if(!control.flickable.dragging && control.flickable.atYBeginning)
0430                 {
0431                     control.returnToBounds()
0432                 }
0433                 
0434                 if (updatingContentY || !control.flickable || !control.flickable.dragging)
0435                 {
0436                     oldContentY = control.flickable.contentY;
0437                     return;
0438                     //TODO: merge
0439                     //if moves but not dragging, just update oldContentY
0440                 }
0441                 
0442                 if(control.flickable.contentHeight < control.height)
0443                 {
0444                     return
0445                 }
0446                 
0447                 var oldFHeight
0448                 var oldHHeight
0449                 
0450                 if (control.footer && control.footerPositioning === ListView.PullBackFooter && control.footer.visible)
0451                 {
0452                     oldFHeight = control.footer.height
0453                     control.footer.height = Math.max(0,
0454                                                      Math.min(control.footer.implicitHeight,
0455                                                               control.footer.height + oldContentY - control.flickable.contentY));
0456                 }
0457                 
0458                 if (control.header && control.headerPositioning === ListView.PullBackHeader && control.header.visible && !control.altHeader)
0459                 {
0460                     oldHHeight = control.header.height
0461                     control.header.height = Math.max(0,
0462                                                      Math.min(control.header.implicitHeight,
0463                                                               control.header.height + oldContentY - control.flickable.contentY));
0464                 }
0465                 
0466                 //if the implicitHeight is changed, use that to simulate scroll
0467                 if (control.header && oldHHeight !== control.header.height && control.header.visible && !control.altHeader)
0468                 {
0469                     updatingContentY = true
0470                     control.flickable.contentY -= (oldHHeight - control.header.height)
0471                     updatingContentY = false
0472                     
0473                 } else {
0474                     oldContentY = control.flickable.contentY
0475                 }
0476             }
0477             
0478             function onMovementEnded()
0479             {
0480                 if (control.header && control.header.visible && control.headerPositioning === ListView.PullBackHeader && !control.altHeader)
0481                 {
0482                     _headerAnimation.enabled = true
0483                     
0484                     if (control.header.height >= (control.header.implicitHeight/2) || control.flickable.atYBeginning )
0485                     {
0486                         control.header.height =  control.header.implicitHeight
0487                         
0488                     } else
0489                     {
0490                         control.header.height = 0
0491                     }
0492                 }
0493                 
0494                 if (control.footer && control.footer.visible && control.footerPositioning === ListView.PullBackFooter)
0495                 {
0496                     _footerAnimation.enabled = true
0497                     
0498                     if (control.footer.height >= (control.footer.implicitHeight/2) ||  control.flickable.atYEnd)
0499                     {
0500                         if(control.flickable.atYEnd)
0501                         {
0502                             control.footer.height =  control.footer.implicitHeight
0503                             
0504                             control.flickable.contentY = control.flickable.contentHeight - control.flickable.height
0505                             oldContentY = control.flickable.contentY
0506                         }else
0507                         {
0508                             control.footer.height =  control.footer.implicitHeight
0509                             
0510                         }
0511                         
0512                     } else
0513                     {
0514                         control.footer.height = 0
0515                     }
0516                 }
0517             }
0518         }
0519         
0520         /**
0521          * @brief The main single header bar.
0522          * By default this header is set to a MauiKit ToolBar, but it can be changed to any other item.
0523          * @see ToolBar
0524          */
0525         property Item header : Maui.ToolBar
0526         {
0527             id: _headBar
0528             visible: count > 0
0529             width: visible ? _headerContent.width : 0
0530             position: control.altHeader ? ToolBar.Footer : ToolBar.Header
0531             Maui.Controls.showCSD: control.Maui.Controls.showCSD && control.Maui.Controls.showCSD === true && !control.altHeader
0532             translucencySource: ShaderEffectSource
0533             {
0534                 sourceItem: _content
0535                 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
0536             }
0537             
0538             Binding on height
0539             {
0540                 value: visible ? _headBar.implicitHeight : 0
0541                 restoreMode: Binding.RestoreBindingOrValue
0542             }
0543             
0544             Behavior on height
0545             {
0546                 id: _headerAnimation
0547                 enabled: false
0548                 NumberAnimation
0549                 {
0550                     duration: Maui.Style.units.shortDuration
0551                     easing.type: Easing.InOutQuad
0552                 }
0553             }
0554             
0555             Component
0556             {
0557                 id: _titleComponent
0558                 
0559                 Item
0560                 {
0561                     implicitHeight:_titleLabel.implicitHeight
0562                     
0563                     Label
0564                     {
0565                         id: _titleLabel
0566                         anchors.fill: parent
0567                         text: control.title
0568                         elide : Text.ElideRight
0569                         font: Maui.Style.h2Font
0570                         horizontalAlignment : Text.AlignHCenter
0571                         verticalAlignment :  Text.AlignVCenter
0572                     }
0573                 }
0574             }
0575             
0576             middleContent: Loader
0577             {
0578                 visible: item
0579                 active: control.title && control.showTitle
0580                 sourceComponent: _titleComponent
0581                 
0582                 asynchronous: true
0583                 
0584                 Layout.fillWidth: true
0585                 Layout.fillHeight: true
0586             }
0587         }
0588         
0589         //Label
0590         //{
0591         //z: 999999999999
0592         //color: "yellow"
0593         //text: _footBar.visibleCount + " / " + _footBar.count + " - " + _footBar.height + " / " + footer.height + " - " + _footBar.visible + " / " + footer.visible + " / " + footer.height + " / " + _footerContent.implicitHeight  + " / " + _footerContent.implicitHeight
0594         //}
0595         
0596         /**
0597          * @brief The main single footer bar.
0598          * By default this footer is set to a MauiKit ToolBar, but it can be changed to any other item.
0599          * @see ToolBar
0600          */
0601         property Item footer : Maui.ToolBar
0602         {
0603             id: _footBar
0604             visible: count > 0
0605             width: visible ? _footerContent.width : 0
0606             height: visible ? implicitHeight : 0
0607             
0608             position: ToolBar.Footer
0609             
0610             translucencySource: ShaderEffectSource
0611             {
0612                 //textureSize: Qt.size(_headBarBG.width * 0.2, _headBarBG.height * 0.2)
0613                 sourceItem: _content
0614                 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)) : null
0615             }
0616             
0617             Behavior on height
0618             {
0619                 id: _footerAnimation
0620                 enabled: false
0621                 NumberAnimation
0622                 {
0623                     duration: Maui.Style.units.shortDuration
0624                     easing.type: Easing.InOutQuad
0625                 }
0626             }
0627         }
0628         
0629         states: [  State
0630         {
0631             when: !altHeader
0632             
0633             AnchorChanges
0634             {
0635                 target: _headerContent
0636                 anchors.top: parent.top
0637                 anchors.bottom: undefined
0638             }
0639             
0640             AnchorChanges
0641             {
0642                 target: _footerContent
0643                 anchors.top: undefined
0644                 anchors.bottom: parent.bottom
0645             }
0646         },
0647         
0648         State
0649         {
0650             when: altHeader
0651             
0652             AnchorChanges
0653             {
0654                 target: _headerContent
0655                 anchors.top: undefined
0656                 anchors.bottom: parent.bottom
0657             }
0658             
0659             AnchorChanges
0660             {
0661                 target: _footerContent
0662                 anchors.top: undefined
0663                 anchors.bottom: _headerContent.top
0664             }
0665         } ]
0666         
0667         onAutoHideHeaderChanged:
0668         {
0669             if(control.autoHideHeader)
0670             {
0671                 pullBackHeader()
0672             }else
0673             {
0674                 pullDownHeader()
0675             }
0676         }
0677         
0678         onAutoHideFooterChanged:
0679         {
0680             if(control.autoHideFooter)
0681             {
0682                 pullBackFooter()
0683             } else
0684             {
0685                 pullDownFooter()
0686             }
0687         }
0688         onAltHeaderChanged: pullDownHeader()
0689         
0690         
0691         //                 Label
0692         //                 {
0693         //                     anchors.centerIn: _headerContent
0694         //                     text: header.height + "/" + _headerContent.height + " - " + _layout.anchors.topMargin
0695         //                     color: "orange"
0696         //                     z: _headerContent.z + 1
0697         //                     visible: header.visible
0698         //                 }
0699         //
0700         //                    Label
0701         //                 {
0702         //                     anchors.centerIn: _footerContent
0703         //                     text: footer.height + "/" + _footerContent.height + " - " + _layout.anchors.topMargin
0704         //                     color: "orange"
0705         //                     z: _footerContent.z + 9999
0706         //                 }
0707         
0708         contentItem: Item
0709         {
0710             Item
0711             {
0712                 id: _content
0713                 anchors.fill: parent
0714                 
0715                 anchors.topMargin: _private.topMargin
0716                 anchors.bottomMargin: _private.bottomMargin
0717                 
0718                 anchors.leftMargin: control.leftMargin
0719                 anchors.rightMargin: control.rightMargin                
0720             }
0721             
0722                 Loader
0723                 {
0724                   active: control.Maui.Controls.showCSD === true && control.altHeader  
0725                     asynchronous: true
0726                                         width: parent.width
0727 
0728                   sourceComponent: Maui.ToolBar
0729                 {
0730                     anchors.top: parent.top
0731                     Maui.Controls.showCSD: true
0732                     background: Rectangle
0733                     {
0734                         Maui.Theme.colorSet: control.Maui.Theme.colorSet
0735                         Maui.Theme.inherit: false
0736                         opacity: 0.8
0737                         scale: -1 //for mirroring
0738                         gradient: Gradient {
0739                             orientation: Gradient.Horizontal
0740         GradientStop { position: 0.0; color: Maui.Theme.backgroundColor }
0741         GradientStop { position: 0.33; color: "transparent" }
0742         GradientStop { position: 1.0; color: "transparent" }
0743     }
0744                     }
0745                 }
0746                 }
0747             
0748             Column
0749             {
0750                 id: _headerContent
0751                 anchors.left: parent.left
0752                 anchors.right: parent.right
0753             }
0754             
0755             Column
0756             {
0757                 id: _footerContent
0758                 anchors.left: parent.left
0759                 anchors.right: parent.right
0760             }
0761             
0762             Loader
0763             {
0764                 anchors.fill: parent
0765                 asynchronous: true
0766                 sourceComponent: MouseArea // to support tbutton go back and forward
0767                 {
0768                     propagateComposedEvents: true
0769                     acceptedButtons: Qt.BackButton | Qt.ForwardButton
0770                     cursorShape: undefined
0771                     
0772                     onPressed: (mouse) =>
0773                     {
0774                         mouse.accepted = false
0775                         if(mouse.button === Qt.BackButton)
0776                         {
0777                             control.goBackTriggered()
0778                         }
0779                         
0780                         if(mouse.button === Qt.ForwardButton)
0781                         {
0782                             control.goForwardTriggered()
0783                         }
0784                     }
0785                 }
0786             }
0787             
0788             Loader
0789             {
0790                 anchors.fill: parent
0791                 asynchronous: true
0792                 z: _content.z +1
0793                 active: (control.autoHideFooter || control.autoHideHeader ) && Maui.Handy.isTouch
0794                 
0795                 sourceComponent: MouseArea
0796                 {
0797                     parent: _content
0798                     propagateComposedEvents: true
0799                     drag.filterChildren: true
0800                     
0801                     Timer
0802                     {
0803                         id: doubleClickTimer
0804                         interval: 900
0805                         onTriggered:
0806                         {
0807                             if(control.autoHideHeader)
0808                             {
0809                                 if(header.height !== 0)
0810                                 {
0811                                     _autoHideHeaderTimer.start()
0812                                     _revealHeaderTimer.stop()
0813                                     
0814                                 }else
0815                                 {
0816                                     _autoHideHeaderTimer.stop()
0817                                     _revealHeaderTimer.start()
0818                                 }
0819                             }
0820                             
0821                             if(control.autoHideFooter)
0822                             {
0823                                 if(footer.height !== 0)
0824                                 {
0825                                     _autoHideFooterTimer.start()
0826                                     
0827                                 }else
0828                                 {
0829                                     pullDownFooter()
0830                                     _autoHideFooterTimer.stop()
0831                                 }
0832                             }
0833                         }
0834                     }
0835                     
0836                     onPressed: (mouse) =>
0837                     {
0838                         doubleClickTimer.restart();
0839                         mouse.accepted = false
0840                     }
0841                 }
0842             }
0843             
0844             Loader
0845             {
0846                 asynchronous: true
0847                 anchors.top: parent.top
0848                 anchors.left: parent.left
0849                 anchors.right: parent.right
0850                 height: active ? _headerContent.implicitHeight + control.autoHideHeaderMargins : 0
0851                 z: _content.z +1
0852                 active: control.autoHideHeader && !control.altHeader && !Maui.Handy.isTouch
0853                 
0854                 sourceComponent: Item
0855                 {                    
0856                     HoverHandler
0857                     {
0858                         target: parent
0859                         acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0860                         
0861                         onHoveredChanged:
0862                         {
0863                             if(!control.autoHideHeader || control.altHeader)
0864                             {
0865                                 _autoHideHeaderTimer.stop()
0866                                 return
0867                             }
0868                             
0869                             if(!hovered)
0870                             {
0871                                 _autoHideHeaderTimer.start()
0872                                 _revealHeaderTimer.stop()
0873                                 
0874                             }else
0875                             {
0876                                 _autoHideHeaderTimer.stop()
0877                                 _revealHeaderTimer.start()
0878                             }
0879                         }
0880                     }
0881                 }
0882             }
0883             
0884             Loader
0885             {
0886                 asynchronous: true
0887                 anchors.bottom: parent.bottom
0888                 anchors.left: parent.left
0889                 anchors.right: parent.right
0890                 height: active ? _footerContent.implicitHeight + control.autoHideFooterMargins : 0
0891                 z: _footerContent.z - 1
0892                 active: control.autoHideFooter && !control.altHeader && !Maui.Handy.isTouch
0893                 
0894                 sourceComponent: Item
0895                 {
0896                     HoverHandler
0897                     {
0898                         target: parent
0899                         
0900                         acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0901                         
0902                         onHoveredChanged:
0903                         {
0904                             if(!control.autoHideFooter)
0905                             {
0906                                 return
0907                             }
0908                             
0909                             if(!hovered)
0910                             {
0911                                 _autoHideFooterTimer.start()
0912                                 
0913                             }else
0914                             {
0915                                 pullDownFooter()
0916                                 _autoHideFooterTimer.stop()
0917                             }
0918                         }
0919                     }
0920                 }
0921             }
0922         }
0923         
0924         Timer
0925         {
0926             id: _revealHeaderTimer
0927             interval: autoHideHeaderDelay
0928             
0929             onTriggered:
0930             {
0931                 pullDownHeader()
0932             }
0933         }
0934         
0935         Timer
0936         {
0937             id: _autoHideHeaderTimer
0938             interval: autoHideHeaderDelay
0939             onTriggered:
0940             {
0941                 if(control.autoHideHeader)
0942                 {
0943                     pullBackHeader()
0944                 }
0945                 
0946                 stop()
0947             }
0948         }
0949         
0950         Timer
0951         {
0952             id: _autoHideFooterTimer
0953             interval: control.autoHideFooterDelay
0954             onTriggered:
0955             {
0956                 if(control.autoHideFooter)
0957                 {
0958                     pullBackFooter()
0959                 }
0960                 
0961                 stop()
0962             }
0963         }
0964         
0965         //Keys.onBackPressed:
0966         //{
0967         //control.goBackTriggered();
0968         //}
0969         
0970         //Shortcut
0971         //{
0972         //sequence: "Forward"
0973         //onActivated: control.goForwardTriggered();
0974         //}
0975         
0976         //Shortcut
0977         //{
0978         //sequence: StandardKey.Forward
0979         //onActivated: control.goForwardTriggered();
0980         //}
0981         
0982         //Shortcut
0983         //{
0984         //sequence: StandardKey.Back
0985         //onActivated: control.goBackTriggered();
0986         //}
0987         
0988         
0989         Component.onCompleted :
0990         {
0991             if(footer)
0992             {
0993                 _footerContent.data.push(footer)
0994             }
0995             
0996             if(header)
0997             {
0998                 let data = [header]
0999                 
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 }