/* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte 0.1 as Latte Item{ id: manager anchors.fill: parent property QtObject window property bool debugMagager: Qt.application.arguments.indexOf("--mask") >= 0 property bool inStartup: root.inStartup property bool normalState : false // this is being set from updateMaskArea property bool previousNormalState : false // this is only for debugging purposes property bool panelIsBiggerFromIconSize: root.useThemePanel && (root.themePanelSize >= root.iconSize) property int animationSpeed: root.durationTime * 1.2 * units.longDuration property bool inSlidingIn: false //necessary because of its init structure property alias inSlidingOut: slidingAnimationAutoHiddenOut.running property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width property int slidingOutToPos: ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) ? -thicknessNormal : thicknessNormal //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations property real iconMarginOriginal: 0.12*plasmoid.configuration.iconSize property int statesLineSizeOriginal: root.latteApplet ? Math.ceil( plasmoid.configuration.iconSize/13 ) : 0 property int thicknessAutoHidden: 2 property int thicknessMid: root.statesLineSize + (1 + (0.65 * (root.zoomFactor-1)))*(root.iconSize+root.iconMargin) //needed in some animations property int thicknessNormal: Math.max(root.statesLineSize + root.iconSize + root.iconMargin + 1, root.realPanelSize + root.panelShadow) property int thicknessZoom: root.statesLineSize + ((root.iconSize+root.iconMargin) * root.zoomFactor) + 2 //it is used to keep thickness solid e.g. when iconSize changes from auto functions property int thicknessMidOriginal: Math.max(thicknessNormalOriginal, statesLineSizeOriginal + (1 + (0.65 * (root.zoomFactor-1)))*(plasmoid.configuration.iconSize+iconMarginOriginal)) //needed in some animations property int thicknessNormalOriginal: Math.max(thicknessNormalOriginalValue, root.realPanelSize + root.panelShadow) property int thicknessNormalOriginalValue: statesLineSizeOriginal + plasmoid.configuration.iconSize + iconMarginOriginal + 1 property int thicknessZoomOriginal: Math.max(statesLineSizeOriginal + ((plasmoid.configuration.iconSize+iconMarginOriginal) * root.zoomFactor) + 2, root.realPanelSize + root.panelShadow) property rect localGeometry: Qt.rect(-1,-1,0,0) Binding{ target: dock property:"maxThickness" when: dock value: thicknessZoomOriginal } Binding{ target: dock property:"normalThickness" when: dock value: thicknessNormalOriginal } Binding{ target: dock property: "drawShadows" when: dock value: root.drawShadowsExternal } Binding{ target: dock property: "maxLength" when: dock value: plasmoid.configuration.maxLength/100 } Binding{ target: dock property: "alignment" when: dock value: root.panelAlignment } onInStartupChanged: { if (!inStartup) { delayAnimationTimer.start(); } } onNormalStateChanged: { if (normalState) { root.updateAutomaticIconSize(); } } onThicknessZoomOriginalChanged: updateMaskArea(); function slotContainsMouseChanged() { if(dock.visibility.containsMouse) { if (delayerTimer.running) { delayerTimer.stop(); } updateMaskArea(); } else { // initialize the zoom delayerTimer.start(); } } function slotMustBeShown() { // console.log("show..."); slidingAnimationAutoHiddenIn.init(); } function slotMustBeHide() { // console.log("hide...."); if(!dock.visibility.blockHiding && !dock.visibility.containsMouse && Latte.WindowSystem.compositingActive) { slidingAnimationAutoHiddenOut.init(); } } ///test maskArea function updateMaskArea() { if (!dock) { return; } var localX = 0; var localY = 0; normalState = ((root.animationsNeedBothAxis === 0) && (root.animationsNeedLength === 0)) || !Latte.WindowSystem.compositingActive || (dock.visibility.isHidden && !dock.visibility.containsMouse && root.animationsNeedThickness == 0); // debug maskArea criteria if (debugMagager) { console.log(root.animationsNeedBothAxis + ", " + root.animationsNeedLength + ", " + root.animationsNeedThickness + ", " + dock.visibility.isHidden); if (previousNormalState !== normalState) { console.log("normal state changed to:" + normalState); previousNormalState = normalState; } } var tempLength = root.isHorizontal ? width : height; var tempThickness = root.isHorizontal ? height : width; var space = root.useThemePanel ? (plasmoid.configuration.panelPosition === Latte.Dock.Justify) ? root.panelEdgeSpacing + 2*root.panelShadow : root.panelEdgeSpacing + 2*root.panelShadow : 2; if (normalState) { //console.log("entered normal state..."); //count panel length if(root.isHorizontal) { tempLength = plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.width + space : mainLayout.width + space; } else { tempLength = plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.height + space : mainLayout.height + space; } tempThickness = thicknessNormal; if (root.animationsNeedThickness > 0) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessMidOriginal : thicknessNormalOriginal; } if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } //configure x,y based on plasmoid position and root.panelAlignment(Alignment) if ((plasmoid.location === PlasmaCore.Types.BottomEdge) || (plasmoid.location === PlasmaCore.Types.TopEdge)) { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localY = dock.height - tempThickness; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localY = 0; } if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { localX = (dock.width/2) - tempLength/2; } else if (root.panelAlignment === Latte.Dock.Left) { localX = 0; } else if (root.panelAlignment === Latte.Dock.Center) { localX = (dock.width/2) - tempLength/2; } else if (root.panelAlignment === Latte.Dock.Right) { localX = dock.width - mainLayout.width - (space/2); } } else if ((plasmoid.location === PlasmaCore.Types.LeftEdge) || (plasmoid.location === PlasmaCore.Types.RightEdge)){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = 0; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localX = dock.width - tempThickness; } if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { localY = (dock.height/2) - tempLength/2; } else if (root.panelAlignment === Latte.Dock.Top) { localY = 0; } else if (root.panelAlignment === Latte.Dock.Center) { localY = (dock.height/2) - tempLength/2; } else if (root.panelAlignment === Latte.Dock.Bottom) { localY = dock.height - mainLayout.height - (space/2); } } } else { if(root.isHorizontal) tempLength = Screen.width; //screenGeometry.width; else tempLength = Screen.height; //screenGeometry.height; //grow only on length and not thickness if(root.animationsNeedLength>0 && root.animationsNeedBothAxis === 0) { //this is used to fix a bug with shadow showing when the animation of edit mode //is triggered var editModeThickness = editModeVisual.editAnimationEnded ? thicknessNormalOriginal + root.editShadow : thicknessNormalOriginal tempThickness = root.editMode ? editModeThickness : thicknessNormalOriginal; if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else if (root.animationsNeedThickness > 0) { tempThickness = thicknessMidOriginal; } } else{ //use all thickness space if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else { tempThickness = thicknessZoomOriginal; } } //configure the x,y position based on thickness if(plasmoid.location === PlasmaCore.Types.RightEdge) localX = dock.width - tempThickness; else if(plasmoid.location === PlasmaCore.Types.BottomEdge) localY = dock.height - tempThickness; } var maskArea = dock.maskArea; var maskLength = maskArea.width; //in Horizontal if (root.isVertical) { maskLength = maskArea.height; } var maskThickness = maskArea.height; //in Horizontal if (root.isVertical) { maskThickness = maskArea.width; } // console.log("Not updating mask..."); if( maskArea.x !== localX || maskArea.y !== localY || maskLength !== tempLength || maskThickness !== tempThickness) { // console.log("Updating mask..."); var newMaskArea = Qt.rect(-1,-1,0,0); newMaskArea.x = localX; newMaskArea.y = localY; if (isHorizontal) { newMaskArea.width = tempLength; newMaskArea.height = tempThickness; } else { newMaskArea.width = tempThickness; newMaskArea.height = tempLength; } if (root.drawShadowsExternal) { dock.maskArea = Qt.rect(0,0,root.width,root.height); } else { dock.maskArea = newMaskArea; } // console.log("update mask area:"+newMaskArea); if((normalState && !dock.visibility.isHidden) || root.editMode){ //the shadows size must be removed from the maskArea //before updating the localDockGeometry var fixedThickness = root.realPanelThickness; if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { newMaskArea.width = fixedThickness; } else { newMaskArea.height = fixedThickness; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { newMaskArea.y = dock.height - fixedThickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { newMaskArea.x = dock.width - fixedThickness; } if (localGeometry.x !== newMaskArea.x || localGeometry.y !== newMaskArea.y || localGeometry.width !== newMaskArea.width || localGeometry.height !== newMaskArea.height) { localGeometry = newMaskArea; dock.setLocalDockGeometry(localGeometry); } // console.log("update dock geometry:"+newMaskArea); } } } Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Item{ anchors.fill:parent Rectangle{ id: windowBackground anchors.fill: parent border.color: "red" border.width: 1 color: "transparent" } Rectangle{ x: dock ? dock.maskArea.x : -1 y: dock ? dock.maskArea.y : -1 height: dock ? dock.maskArea.height : 0 width: dock ? dock.maskArea.width : 0 border.color: "green" border.width: 1 color: "transparent" } } } /***Hiding/Showing Animations*****/ //////////////// Animations - Slide In - Out SequentialAnimation{ id: slidingAnimationAutoHiddenOut ScriptAction{ script: dock.visibility.isHidden = true; } PropertyAnimation { target: layoutsContainer property: root.isVertical ? "x" : "y" to: slidingOutToPos duration: manager.animationSpeed easing.type: Easing.OutQuad } onStarted: { if (manager.debugMagager) { console.log("hiding animation started..."); } } onStopped: { if (manager.debugMagager) { console.log("hiding animation ended..."); } updateMaskArea(); } function init() { if (!dock.visibility.blockHiding) start(); } } SequentialAnimation{ id: slidingAnimationAutoHiddenIn PropertyAnimation { target: layoutsContainer property: root.isVertical ? "x" : "y" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } onStarted: { if (manager.debugMagager) { console.log("showing animation started..."); } } onStopped: { inSlidingIn = false; if (manager.debugMagager) { console.log("showing animation ended..."); } } function init() { // if (!dock.visibility.blockHiding) inSlidingIn = true; if (slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.stop(); } dock.visibility.isHidden = false; updateMaskArea(); start(); } } ////////////// Timers ////// //Timer to delay onLeave event Timer { id: delayerTimer interval: 400 onTriggered: { if (!root.containsMouse()) { root.clearZoom(); } } } //Timer to delay onLeave event Timer { id: delayAnimationTimer interval: manager.inStartup ? 1000 : 500 onTriggered: { layoutsContainer.opacity = 1; if (dock.visibility.mode !== Latte.Dock.AutoHide) { slidingAnimationAutoHiddenIn.init(); } } } }