Warning, /plasma/latte-dock/containment/package/contents/ui/layouts/LayoutsContainer.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org>
0003     SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.1
0008 import QtQuick.Layouts 1.1
0009 
0010 import org.kde.plasma.plasmoid 2.0
0011 
0012 import org.kde.plasma.core 2.0 as PlasmaCore
0013 
0014 import org.kde.latte.private.app 0.1 as LatteApp
0015 import org.kde.latte.core 0.2 as LatteCore
0016 import org.kde.latte.private.containment 0.1 as LatteContainment
0017 
0018 import "../debugger" as Debugger
0019 
0020 Item{
0021     id: layoutsContainer
0022     //! WorkAround: Do not use "visible" because when it becomes "false" the contained applets can hide/show their elements.
0023     //! That approach can create a conflict with Latte Tasks that after showing the view they reshow windows
0024     //! that were already shown before hiding.
0025     //! visible: !(latteView && latteView.visibility.isHidden)
0026     opacity: !(latteView && latteView.visibility.isHidden) ? 1 : 0
0027 
0028     readonly property bool isHidden: root.inStartup || (latteView && latteView.visibility && latteView.visibility.isHidden)
0029 
0030     property int currentSpot: -1000
0031 
0032     readonly property alias startLayout : _startLayout
0033     readonly property alias mainLayout: _mainLayout
0034     readonly property alias endLayout: _endLayout
0035     readonly property alias contextMenuIsShown: contextMenuLayer.menuIsShown
0036 
0037     signal contentsLengthChanged();
0038 
0039     Binding {
0040         target: layoutsContainer
0041         property: "x"
0042         when: !visibilityManager.inRelocationAnimation
0043         value: {
0044             if (root.behaveAsPlasmaPanel) {
0045                 return 0;
0046             }
0047 
0048             if ( latteView && root.isHorizontal && root.myView.alignment === LatteCore.Types.Justify ){
0049                 return ((latteView.width/2) - (root.maxLength/2) + background.offset);
0050             } else {
0051                 if ((root.myView.inSlidingIn || root.myView.inSlidingOut) && root.isVertical){
0052                     return;
0053                 }
0054 
0055                 if (layoutsContainer.isHidden && root.isVertical) {
0056                     if (LatteCore.WindowSystem.compositingActive) {
0057                         return visibilityManager.slidingOutToPos;
0058                     } else {
0059                         if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) {
0060                             return visibilityManager.slidingOutToPos + 1;
0061                         } else {
0062                             return visibilityManager.slidingOutToPos - 1;
0063                         }
0064                     }
0065                 } else {
0066                     return 0;
0067                 }
0068             }
0069         }
0070     }
0071 
0072     Binding{
0073         target: layoutsContainer
0074         property: "y"
0075         when: !visibilityManager.inRelocationAnimation
0076         value: {
0077             if (root.behaveAsPlasmaPanel) {
0078                 return 0;
0079             }
0080 
0081             if ( latteView && root.isVertical && root.myView.alignment === LatteCore.Types.Justify ) {
0082                 return ((latteView.height/2) - (root.maxLength/2) + background.offset);
0083             } else {
0084                 if ((root.myView.inSlidingIn || root.myView.inSlidingOut) && root.isHorizontal){
0085                     return;
0086                 }
0087 
0088                 if (layoutsContainer.isHidden && root.isHorizontal) {
0089                     if (LatteCore.WindowSystem.compositingActive) {
0090                         return visibilityManager.slidingOutToPos;
0091                     } else {
0092                         if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) {
0093                             return visibilityManager.slidingOutToPos + 1;
0094                         } else {
0095                             return visibilityManager.slidingOutToPos - 1;
0096                         }
0097                     }
0098                 } else {
0099                     return 0;
0100                 }
0101             }
0102         }
0103     }
0104 
0105     width: root.isHorizontal && root.myView.alignment === LatteCore.Types.Justify ? root.maxLength : parent.width
0106     height: root.isVertical && root.myView.alignment === LatteCore.Types.Justify ? root.maxLength : parent.height
0107     z:10
0108 
0109     property bool animationSent: false
0110     property bool shouldCheckHalfs: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (_mainLayout.children>1)
0111 
0112     property int contentsWidth: root.isHorizontal ? _startLayout.width + _mainLayout.width + _endLayout.width :
0113                                                     Math.max(_startLayout.width, _mainLayout.width ,_endLayout.width)
0114     property int contentsHeight: root.isVertical ? _startLayout.height + _mainLayout.height + _endLayout.height :
0115                                                    Math.max(_startLayout.height, _mainLayout.height, _endLayout.height)
0116 
0117 
0118     readonly property int backgroundShadowTailLength: {
0119         if (root.behaveAsPlasmaPanel) {
0120             return 0;
0121         }
0122 
0123         if (root.myView.alignment === LatteCore.Types.Left) {
0124             return background.shadows.left;
0125         } else if (root.myView.alignment === LatteCore.Types.Right) {
0126             return background.shadows.right;
0127         } else if (root.myView.alignment === LatteCore.Types.Top) {
0128             return background.shadows.top;
0129         } else if (root.myView.alignment === LatteCore.Types.Bottom) {
0130             return background.shadows.bottom;
0131         }
0132 
0133         //! centered case
0134         return root.isHorizontal ? background.shadows.left : background.shadows.top;
0135     }
0136 
0137     readonly property int backgroundShadowHeadLength: {
0138         if (root.behaveAsPlasmaPanel) {
0139             return 0;
0140         }
0141 
0142         if (root.myView.alignment === LatteCore.Types.Left) {
0143             return background.shadows.right;
0144         } else if (root.myView.alignment === LatteCore.Types.Right) {
0145             return background.shadows.left;
0146         } else if (root.myView.alignment === LatteCore.Types.Top) {
0147             return background.shadows.bottom;
0148         } else if (root.myView.alignment === LatteCore.Types.Bottom) {
0149             return background.shadows.top;
0150         }
0151 
0152         //! centered case
0153         return root.isHorizontal ? background.shadows.right : background.shadows.bottom;
0154     }
0155 
0156     readonly property int lengthTailPadding: {
0157         var minimumPadding = metrics.margin.length;
0158         var bestMatchingPadding = 0;
0159 
0160         if (root.myView.alignment === LatteCore.Types.Left) {
0161             bestMatchingPadding = Math.max(background.paddings.left, minimumPadding) - minimumPadding;
0162         } else if (root.myView.alignment === LatteCore.Types.Right) {
0163             bestMatchingPadding = Math.max(background.paddings.right, minimumPadding) - minimumPadding;
0164         } else if (root.myView.alignment === LatteCore.Types.Top) {
0165             bestMatchingPadding = Math.max(background.paddings.top, minimumPadding) - minimumPadding;
0166         } else if (root.myView.alignment === LatteCore.Types.Bottom) {
0167             bestMatchingPadding = Math.max(background.paddings.bottom, minimumPadding) - minimumPadding;
0168         } else if (root.myView.alignment === LatteCore.Types.Center) {
0169             bestMatchingPadding = Math.max(background.paddings.left, minimumPadding) - minimumPadding;
0170         } else if (root.myView.alignment === LatteCore.Types.Justify) {
0171             var backpadding = root.isHorizontal ? background.paddings.left : background.paddings.top;
0172             bestMatchingPadding = Math.max(backpadding, minimumPadding) - minimumPadding;
0173         }
0174 
0175         //shadow is already calculated in Justify mode
0176         return root.myView.alignment !== LatteCore.Types.Justify ? backgroundShadowTailLength + bestMatchingPadding : bestMatchingPadding;
0177     }
0178 
0179     readonly property int lengthHeadPadding: {
0180         var minimumPadding = metrics.margin.length;
0181         var bestMatchingPadding = 0;
0182 
0183         if (root.myView.alignment === LatteCore.Types.Left) {
0184             bestMatchingPadding = Math.max(background.paddings.right, minimumPadding) - minimumPadding;
0185         } else if (root.myView.alignment === LatteCore.Types.Right) {
0186             bestMatchingPadding = Math.max(background.paddings.left, minimumPadding) - minimumPadding;
0187         } else if (root.myView.alignment === LatteCore.Types.Top) {
0188             bestMatchingPadding = Math.max(background.paddings.bottom, minimumPadding) - minimumPadding;
0189         } else if (root.myView.alignment === LatteCore.Types.Bottom) {
0190             bestMatchingPadding = Math.max(background.paddings.top, minimumPadding) - minimumPadding;
0191         } else if (root.myView.alignment === LatteCore.Types.Center) {
0192             bestMatchingPadding = Math.max(background.paddings.right, minimumPadding) - minimumPadding;
0193         } else if (root.myView.alignment === LatteCore.Types.Justify) {
0194             var backpadding = root.isHorizontal ? background.paddings.right : background.paddings.bottom;
0195             bestMatchingPadding = Math.max(backpadding, minimumPadding) - minimumPadding;
0196         }
0197 
0198         //shadow is already calculated in Justify mode
0199         return root.myView.alignment !== LatteCore.Types.Justify ? backgroundShadowHeadLength + bestMatchingPadding : bestMatchingPadding;
0200     }
0201 
0202     onContentsWidthChanged: {
0203         if (root.isHorizontal){
0204             var firstHalfExited = false;
0205             var secondHalfExited = false;
0206 
0207             if (shouldCheckHalfs){
0208                 firstHalfExited = ( (_startLayout.width + _mainLayout.width/2) >= root.maxLength/2 );
0209                 secondHalfExited = ( (_endLayout.width + _mainLayout.width/2) >= root.maxLength/2 );
0210             }
0211 
0212             if (latteView && ((contentsWidth >= root.maxLength) || firstHalfExited || secondHalfExited)) {
0213                 autosize.updateIconSize();
0214             }
0215 
0216             if (!animationSent) {
0217                 animationSent = true;
0218                 animations.needLength.addEvent(layoutsContainer);
0219             }
0220 
0221             contentsLengthChanged();
0222 
0223             delayUpdateMaskArea.start();
0224         }
0225     }
0226 
0227     onContentsHeightChanged: {
0228         if (root.isVertical){
0229             var firstHalfExited = false;
0230             var secondHalfExited = false;
0231 
0232             if (shouldCheckHalfs){
0233                 firstHalfExited = ( (_startLayout.height + _mainLayout.height/2) >= root.maxLength/2 );
0234                 secondHalfExited = ( (_endLayout.height + _mainLayout.height/2) >= root.maxLength/2 );
0235             }
0236 
0237             if (latteView && ((contentsHeight >= root.maxLength) || firstHalfExited || secondHalfExited)) {
0238                 autosize.updateIconSize();
0239             }
0240 
0241             if (!animationSent) {
0242                 animationSent = true;
0243                 animations.needLength.removeEvent(layoutsContainer);
0244             }
0245 
0246             contentsLengthChanged();
0247 
0248             delayUpdateMaskArea.start();
0249         }
0250     }
0251 
0252     onXChanged: root.updateEffectsArea();
0253     onYChanged: root.updateEffectsArea();
0254 
0255     EnvironmentActions {
0256         id: environmentActions
0257         active: root.scrollAction !== LatteContainment.Types.ScrollNone || root.dragActiveWindowEnabled || root.closeActiveWindowEnabled
0258         alignment: _mainLayout.alignment
0259     }
0260 
0261     LatteApp.ContextMenuLayer {
0262         id: contextMenuLayer
0263         anchors.fill: parent
0264         view: latteView
0265     }
0266 
0267     AppletsContainer {
0268         id: _startLayout
0269         beginIndex: 0
0270         offset: lengthTailPadding
0271         alignment: {
0272             switch(plasmoid.location) {
0273             case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeLeftAlign;
0274             case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeLeftAlign;
0275             case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeTopAlign;
0276             case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeTopAlign;
0277             }
0278 
0279             return LatteCore.Types.BottomEdgeLeftAlign;
0280         }
0281     }
0282 
0283     /*Rectangle {
0284         anchors.fill: _mainLayout
0285         color: "transparent"
0286         border.width: 1
0287         border.color: "black"
0288     }*/
0289 
0290     AppletsContainer {
0291         id: _mainLayout
0292         z:10 //be on top of start and end layouts
0293         beginIndex: 100
0294         offset: {
0295             if (!centered) {
0296                 //! it is used for Top/Bottom/Left/Right alignments when they show both background length shadows
0297                 return background.offset + lengthTailPadding;
0298             }
0299 
0300             return (root.myView.alignment === LatteCore.Types.Justify) ? inJustifyCenterOffset : background.offset - parabolicOffsetting
0301         }
0302 
0303         ignoredLength: startParabolicSpacer.length + endParabolicSpacer.length
0304 
0305         readonly property alias startParabolicSpacer: _startParabolicSpacer
0306         readonly property alias endParabolicSpacer: _endParabolicSpacer
0307 
0308         readonly property bool centered: (root.myView.alignment === LatteCore.Types.Center) || (root.myView.alignment === LatteCore.Types.Justify)
0309         readonly property bool reversed: Qt.application.layoutDirection === Qt.RightToLeft
0310         readonly property real parabolicOffsetting: (startParabolicSpacer.length - endParabolicSpacer.length) / 2
0311         property int inJustifyCenterOffset: 0
0312 
0313         alignment: {
0314             if (plasmoid.location === PlasmaCore.Types.LeftEdge) {
0315                 if (centered) return LatteCore.Types.LeftEdgeCenterAlign;
0316                 if (root.myView.alignment === LatteCore.Types.Top) return LatteCore.Types.LeftEdgeTopAlign;
0317                 if (root.myView.alignment === LatteCore.Types.Bottom) return LatteCore.Types.LeftEdgeBottomAlign;
0318             }
0319 
0320             if (plasmoid.location === PlasmaCore.Types.RightEdge) {
0321                 if (centered) return LatteCore.Types.RightEdgeCenterAlign;
0322                 if (root.myView.alignment === LatteCore.Types.Top) return LatteCore.Types.RightEdgeTopAlign;
0323                 if (root.myView.alignment === LatteCore.Types.Bottom) return LatteCore.Types.RightEdgeBottomAlign;
0324             }
0325 
0326             if (plasmoid.location === PlasmaCore.Types.BottomEdge) {
0327                 if (centered) return LatteCore.Types.BottomEdgeCenterAlign;
0328 
0329                 if ((root.myView.alignment === LatteCore.Types.Left && !reversed)
0330                         || (root.myView.alignment === LatteCore.Types.Right && reversed)) {
0331                     return LatteCore.Types.BottomEdgeLeftAlign;
0332                 }
0333 
0334                 if ((root.myView.alignment === LatteCore.Types.Right && !reversed)
0335                         || (root.myView.alignment === LatteCore.Types.Left && reversed)) {
0336                     return LatteCore.Types.BottomEdgeRightAlign;
0337                 }
0338             }
0339 
0340             if (plasmoid.location === PlasmaCore.Types.TopEdge) {
0341                 if (centered) return LatteCore.Types.TopEdgeCenterAlign;
0342 
0343                 if ((root.myView.alignment === LatteCore.Types.Left && !reversed)
0344                         || (root.myView.alignment === LatteCore.Types.Right && reversed)) {
0345                     return LatteCore.Types.TopEdgeLeftAlign;
0346                 }
0347 
0348                 if ((root.myView.alignment === LatteCore.Types.Right && !reversed)
0349                         || (root.myView.alignment === LatteCore.Types.Left && reversed)) {
0350                     return LatteCore.Types.TopEdgeRightAlign;
0351                 }
0352             }
0353 
0354             return LatteCore.Types.BottomEdgeCenterAlign;
0355         }
0356 
0357         transitions: Transition {
0358             enabled: !visibilityManager.inRelocationAnimation && !root.inStartup
0359             AnchorAnimation {
0360                 duration: 0.8 * animations.duration.proposed
0361                 easing.type: Easing.OutCubic
0362             }
0363         }
0364 
0365         ParabolicEdgeSpacer {
0366             id: _startParabolicSpacer
0367             index: mainLayout.beginIndex - 1
0368         }
0369 
0370         ParabolicEdgeSpacer {
0371             id: _endParabolicSpacer
0372             index: mainLayout.beginIndex + mainLayout.children.length - 2
0373         }
0374 
0375         Binding{
0376             target: _mainLayout
0377             property:"inJustifyCenterOffset"
0378             when: !layouter.appletsInParentChange && layouter.inNormalFillCalculationsState
0379             value: {
0380                 if (root.myView.alignment !== LatteCore.Types.Justify) {
0381                     return 0;
0382                 }
0383 
0384                 var layoutMaxLength = root.maxLength / 2;
0385                 var sideLayoutMaxLength = layoutMaxLength - mainLayout.length/2;
0386                 var sideslength = startLayout.length + endLayout.length;
0387 
0388                 if (sideslength > root.maxLength) {
0389                     return 0;
0390                 }
0391 
0392                 if (startLayout.length > sideLayoutMaxLength) {
0393                     return (startLayout.length - sideLayoutMaxLength);
0394                 } else if (endLayout.length > sideLayoutMaxLength) {
0395                     return -(endLayout.length - sideLayoutMaxLength);
0396                 }
0397 
0398                 return 0;
0399             }
0400         }
0401     }
0402 
0403     AppletsContainer {
0404         id: _endLayout
0405         beginIndex: 200
0406         offset: lengthHeadPadding
0407         alignment: {
0408             switch(plasmoid.location) {
0409             case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeRightAlign;
0410             case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeRightAlign;
0411             case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeBottomAlign;
0412             case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeBottomAlign;
0413             }
0414 
0415             return LatteCore.Types.BottomEdgeLeftAlign;
0416         }
0417     }
0418 
0419     Connections {
0420         target: metrics
0421         onIconSizeAnimationEnded: delayUpdateMaskArea.start();
0422     }
0423 
0424     //! Debug Elements
0425     Loader{
0426         anchors.top: startLayout.top
0427         anchors.horizontalCenter: startLayout.horizontalCenter
0428         active: debug.layouterEnabled
0429 
0430         readonly property Item debugLayout: layouter.startLayout
0431 
0432         sourceComponent: Debugger.Tag{
0433             background.color: "white"
0434             label.text: tagText
0435             label.color: "black"
0436             label.font.pointSize: 13
0437             readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height
0438 
0439             readonly property string tagText: {
0440                 return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength;
0441             }
0442         }
0443     }
0444 
0445     Loader{
0446         anchors.top: endLayout.top
0447         anchors.horizontalCenter: endLayout.horizontalCenter
0448         active: debug.layouterEnabled
0449 
0450         readonly property Item debugLayout: layouter.endLayout
0451 
0452         sourceComponent: Debugger.Tag{
0453             background.color: "white"
0454             label.text: tagText
0455             label.color: "black"
0456             label.font.pointSize: 13
0457             readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height
0458 
0459             readonly property string tagText: {
0460                 return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength;
0461             }
0462         }
0463     }
0464 
0465     Loader{
0466         anchors.top: mainLayout.top
0467         anchors.horizontalCenter: mainLayout.horizontalCenter
0468         active: debug.layouterEnabled
0469         z:70
0470 
0471         readonly property Item debugLayout: layouter.mainLayout
0472 
0473         sourceComponent: Debugger.Tag{
0474             background.color: "white"
0475             label.text: tagText
0476             label.color: "black"
0477             label.font.pointSize: 13
0478             readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height
0479 
0480             readonly property string tagText: {
0481                 return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength;
0482             }
0483         }
0484     }
0485 
0486     Loader{
0487         anchors.top: mainLayout.top
0488         anchors.left: parent.left
0489         active: debug.layouterEnabled
0490 
0491         readonly property Item debugLayout: layoutsContainer
0492 
0493         sourceComponent: Debugger.Tag{
0494             background.color: "blue"
0495             label.text: tagText
0496             label.color: "yellow"
0497             label.font.pointSize: 13
0498             label.font.bold: true
0499             readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height
0500 
0501             readonly property int layoutsLength: {
0502                 if (root.isVertical) {
0503                     return layouter.startLayout.grid.height + layouter.mainLayout.grid.height + layouter.endLayout.grid.height;
0504                 }
0505 
0506                 return layouter.startLayout.grid.width + layouter.mainLayout.grid.width + layouter.endLayout.grid.width;
0507             }
0508 
0509             readonly property string tagText: {
0510                 return "MAX:" + root.maxLength + " / MIN: " + root.minLength + " TOT:"+layoutLength + " / LAYS:"+ layoutsLength;
0511             }
0512         }
0513     }
0514 
0515     //! This timer is needed in order to update mask area after ContentsWidth/Height and iconSize changes
0516     Timer{
0517         id:delayUpdateMaskArea
0518         repeat:false;
0519         interval:300;
0520 
0521         onTriggered: {
0522             if (layoutsContainer.animationSent) {
0523                 animations.needLength.removeEvent(layoutsContainer);
0524                 layoutsContainer.animationSent = false;
0525             }
0526 
0527             visibilityManager.updateMaskArea();
0528 
0529             if (debug.timersEnabled) {
0530                 console.log("LayoutsContainer timer: delayUpdateMaskArea called...");
0531             }
0532         }
0533     }
0534 }