diff --git a/containment/package/contents/code/HeuristicTools.js b/containment/package/contents/code/HeuristicTools.js deleted file mode 100644 index 9355f923..00000000 --- a/containment/package/contents/code/HeuristicTools.js +++ /dev/null @@ -1,336 +0,0 @@ -/* -* Copyright 2017-2018 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 . -*/ - -//! FILLWIDTH/FILLHEIGHT COMPUTATIONS -//! Computations in order to calculate correctly the sizes for applets -//! that are requesting fillWidth or fillHeight - -//! qBound style function that is specialized in Layouts -//! meaning that -1 values are ignored for fillWidth(s)/Height(s) -function layoutBound(min, pref, max){ - if (max === -1) { - max = pref === -1 ? min : pref; - } - - if (pref === -1) { - pref = max === -1 ? min : pref; - } - - return Math.min(Math.max(min,pref),max); -} - - -//! initialize AppletItems flag "inFillCalculations" in order -//! to inform them that new calculations are taking place -function initLayoutForFillsCalculations(layout) { - for(var i=0; i=0 && minSize!==Infinity ? minSize : -1; - prefSize = minSize>=0 && prefSize!==Infinity ? prefSize : -1; - maxSize = maxSize>=0 && maxSize!== Infinity ? maxSize : -1; - - var appliedSize = -1; - - //! check if the applet does not provide any valid metrics and for that case - //! the system must decide what space to be given after the applets that provide - //! nice metrics are assigned their sizes - var systemDecide = ((minSize<0) && (prefSize<0) && (maxSize<0)); - - if (!systemDecide) { - if (noOfApplets>1) { - appliedSize = layoutBound(minSize, prefSize, maxSize); - - // console.log( " s3_1 " + curApplet.applet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); - } else if (noOfApplets===1) { - //! at this step if only one applet has remained for which the max size is not null, - //! then for this applet we make sure the maximum size does not exceed the available space - //! in order for the applet to not be drawn outside the boundaries - appliedSize = layoutBound(minSize, prefSize, Math.min(maxSize, sizePerApplet)); - - // console.log( " s3_2 " + curApplet.applet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); - } - - //! appliedSize is valid and is also lower than the availableSpace, if it is not lower then - //! for this applet the needed space will be provided as a second pass in a fair way - //! between all remained applets that did not gain a valid fill space - if (appliedSize>=0 && appliedSize<=sizePerApplet) { - var properSize = Math.min(appliedSize, availableSpace); - var thickness = root.isVertical ? root.width : root.height; - var adjustedSize = curApplet.isHidden ? 0 : Math.max(thickness, properSize); - - curApplet.sizeForFill = adjustedSize; - curApplet.inFillCalculations = false; - availableSpace = Math.max(0, availableSpace - curApplet.sizeForFill); - noOfApplets = noOfApplets - 1; - sizePerApplet = noOfApplets > 1 ? Math.floor(availableSpace / noOfApplets) : availableSpace; - - // console.log( " s3_3 " + curApplet.applet.pluginName + " assigned: " + curApplet.sizeForFill); - } - } - - // console.log("s3_r " +curApplet.applet.pluginName + " : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets + "\n"); - } - } - } - - return [availableSpace, sizePerApplet, noOfApplets]; -} - -//! during step2/pass2 all the applets with fills -//! that remained with no computations from pass1 -//! are updated with the algorithm's proposed size -function computeStep2ForLayout(layout, sizePerApplet, noOfApplets) { - if (sizePerApplet>0) { - if (noOfApplets === 0) { - //! when all applets have assigned some size and there is still free space, we must find - //! the most demanding space applet and assign the remaining space to it - - var mostDemandingAppletSize = 0; - var mostDemandingApplet = undefined; - - //! applets with no strong opinion - var neutralAppletsNo = 0; - var neutralApplets = []; - - for(var i=0; imostDemandingAppletSize) { - mostDemandingApplet = curApplet; - mostDemandingAppletSize = curApplet.sizeForFill; - } else if (isNeutral) { - neutralAppletsNo = neutralAppletsNo + 1; - neutralApplets.push(curApplet); - } - } - } - - if (mostDemandingApplet) { - //! the most demanding applet gains all the remaining space - mostDemandingApplet.sizeForFill = mostDemandingApplet.sizeForFill + sizePerApplet; - - // console.log("s4_1 "+ mostDemandingApplet.applet.pluginName + " assigned: " + mostDemandingApplet.sizeForFill + "\n"); - } else if (neutralAppletsNo>0) { - //! if no demanding applets was found then the available space is splitted equally - //! between all neutralApplets - var adjustedAppletSize = (sizePerApplet / neutralAppletsNo); - for (var j=0; jNo values. For step2 passing value!=0 - //! means default step2 behavior BUT value=0 means that remained space - //! must be also assigned at the end. - var remainedSpace = (noA === 0 && sizePerApplet > 0) ? true : false - - var startNo = -1; - var mainNo = -1; - var endNo = -1; - - if (remainedSpace) { - if (startLayout.fillApplets > 0) { - startNo = 0; - } else if (endLayout.fillApplets > 0) { - endNo = 0; - } else if (mainLayout.fillApplets > 0) { - mainNo = 0; - } - } - - //! second pass in order to update sizes for applet that want to fill space - //! these applets get the direct division of the available free space that - //! remained from step1 OR the the free available space that no applet requested yet - - computeStep2ForLayout(startLayout, sizePerApplet, startNo); //default behavior - computeStep2ForLayout(mainLayout, sizePerApplet, mainNo); //default behavior - computeStep2ForLayout(endLayout, sizePerApplet, endNo); //default behavior - - //console.log("s5..."); - } else { - //! Justify mode in all remaining cases - - // console.log(" S3 _ SIZES ::: " + root.maxLength + " ___ " + startLayout.sizeWithNoFillApplets + " ___ " + mainLayout.sizeWithNoFillApplets + " ___ " + endLayout.sizeWithNoFillApplets); - - //! compute the two free spaces around the centered layout - //! they are called start and end accordingly - var halfMainLayout = mainLayout.sizeWithNoFillApplets / 2; - var availableSpaceStart = Math.max(0, root.maxLength/2 - startLayout.sizeWithNoFillApplets - halfMainLayout - root.panelEdgeSpacing/2); - var availableSpaceEnd = Math.max(0, root.maxLength/2 - endLayout.sizeWithNoFillApplets - halfMainLayout - root.panelEdgeSpacing/2); - var availableSpace = availableSpaceStart + availableSpaceEnd - mainLayout.sizeWithNoFillApplets; - - var sizePerAppletMain = mainLayout.fillApplets > 0 ? availableSpace / noA : 0 ; - - var noStart = startLayout.fillApplets; - var noMain = mainLayout.fillApplets; - var noEnd = endLayout.fillApplets; - - //! initialize the computations - initLayoutForFillsCalculations(startLayout); - initLayoutForFillsCalculations(mainLayout); - initLayoutForFillsCalculations(endLayout); - - var res; - - //! first pass - if (mainLayout.fillApplets > 0){ - res = computeStep1ForLayout(mainLayout, availableSpace, sizePerAppletMain, noMain); - sizePerAppletMain = res[1]; noMain = res[2]; - var dif = (availableSpace - res[0]) / 2; - availableSpaceStart = availableSpaceStart - dif; - availableSpaceEnd = availableSpaceEnd - dif; - } - - var sizePerAppletStart = startLayout.fillApplets > 0 ? availableSpaceStart / noStart : 0 ; - var sizePerAppletEnd = endLayout.fillApplets > 0 ? availableSpaceEnd / noEnd : 0 ; - - if (startLayout.fillApplets > 0) { - res = computeStep1ForLayout(startLayout, availableSpaceStart, sizePerAppletStart, noStart); - availableSpaceStart = res[0]; sizePerAppletStart = res[1]; noStart = res[2]; - } - if (endLayout.fillApplets > 0) { - res = computeStep1ForLayout(endLayout, availableSpaceEnd, sizePerAppletEnd, noEnd); - availableSpaceEnd = res[0]; sizePerAppletEnd = res[1]; noEnd = res[2]; - } - - //// - //! second pass - - // console.log(" S ::: " +startLayout.fillApplets + " _ " + sizePerAppletStart + " _ " + noStart); - - if (mainLayout.fillApplets > 0) { - computeStep2ForLayout(mainLayout, sizePerAppletMain, noMain); //default behavior - } - - if (startLayout.fillApplets > 0) { - computeStep2ForLayout(startLayout, sizePerAppletStart, noStart); - } - - if (endLayout.fillApplets > 0) { - computeStep2ForLayout(endLayout, sizePerAppletEnd, noEnd); - } - } - } -} diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index decb3497..c88edff6 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -1,1033 +1,1033 @@ /* * 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.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment Item{ id: manager anchors.fill: parent property QtObject window property bool debugManager: Qt.application.arguments.indexOf("--mask") >= 0 property bool blockUpdateMask: false property bool inForceHiding: false //is used when the docks are forced in hiding e.g. when changing layouts 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 && (background.totals.visualThickness >= (metrics.iconSize + metrics.margin.thickness)) property bool maskIsFloating: !root.behaveAsPlasmaPanel && !root.editMode && screenEdgeMarginEnabled && !plasmoid.configuration.fittsLawIsRequested && !inSlidingIn && !inSlidingOut property int maskFloatedGap: maskIsFloating ? Math.max(0, metrics.margin.screenEdge - background.shadows.headThickness) : 0 property int animationSpeed: LatteCore.WindowSystem.compositingActive ? (editModeVisual.inEditMode ? editModeVisual.speed * 0.8 : animations.speedFactor.normal * 1.62 * animations.duration.large) : 0 property bool inLocationAnimation: latteView && latteView.positioner && latteView.positioner.inLocationAnimation property bool inSlidingIn: false //necessary because of its init structure property alias inSlidingOut: slidingAnimationAutoHiddenOut.running property bool inTempHiding: false property bool inScreenEdgeInternalWindowSliding: root.behaveAsDockWithMask && hideThickScreenGap property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width property int slidingOutToPos: { if (root.behaveAsPlasmaPanel) { var edgeMargin = screenEdgeMarginEnabled ? plasmoid.configuration.screenEdgeMargin : 0 root.isHorizontal ? root.height + edgeMargin - 1 : root.width + edgeMargin - 1; } else { var topOrLeftEdge = ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)); return (topOrLeftEdge ? -thicknessNormal : thicknessNormal); } } property int finalScreenEdgeMargin: { //! is used for window geometry calculations if (!screenEdgeMarginEnabled || (hideThickScreenGap && metrics.margin.screenEdge === 0)) { /*window geometry is updated after the local screen margin animation was zeroed*/ return 0; } return plasmoid.configuration.screenEdgeMargin; } property int thicknessAutoHidden: LatteCore.WindowSystem.compositingActive ? 2 : 1 property int thicknessMid: finalScreenEdgeMargin + (1 + (0.65 * (parabolic.factor.maxZoom-1)))*(metrics.totals.thickness+extraZoomThickMask) //needed in some animations property int thicknessNormal: finalScreenEdgeMargin + Math.max(metrics.totals.thickness + extraNormalThickMask + 1, background.thickness + background.shadows.headThickness) property int thicknessZoom: finalScreenEdgeMargin + ((metrics.totals.thickness+extraZoomThickMask) * parabolic.factor.maxZoom) + 2 //it is used to keep thickness solid e.g. when iconSize changes from auto functions property int thicknessMidOriginal: finalScreenEdgeMargin + Math.max(thicknessNormalOriginal,extraNormalThickMask + (1 + (0.65 * (parabolic.factor.maxZoom-1)))*(metrics.maxIconSize+metrics.margin.maxThickness)) //needed in some animations property int thicknessNormalOriginal: finalScreenEdgeMargin + metrics.maxIconSize + (metrics.margin.maxThickness * 2) //this way we always have the same thickness published at all states /*property int thicknessNormalOriginal: !root.behaveAsPlasmaPanel || root.editMode ? thicknessNormalOriginalValue : background.thickness + background.shadows.headThickness*/ property int thicknessNormalOriginalValue: finalScreenEdgeMargin + metrics.maxIconSize + (metrics.margin.maxThickness * 2) + extraNormalThickMask + 1 property int thicknessZoomOriginal: finalScreenEdgeMargin + Math.max( ((metrics.maxIconSize+(metrics.margin.maxThickness * 2)) * parabolic.factor.maxZoom) + extraZoomThickMask + 2, background.thickness + background.shadows.headThickness, (LatteCore.WindowSystem.compositingActive ? thicknessEditMode + root.editShadow : thicknessEditMode)) //! is used from Panel in edit mode in order to provide correct masking property int thicknessEditMode: thicknessNormalOriginalValue + editModeVisual.settingsThickness //! when Latte behaves as Plasma panel property int thicknessAsPanel: metrics.totals.thickness //! is used to increase the mask thickness readonly property int marginBetweenContentsAndRuler: 10 property int extraNormalThickMask: Math.max(indicatorsExtraThickMask, shadowsExtraThickMask) property int extraZoomThickMask: marginBetweenContentsAndRuler + Math.max(indicatorsExtraThickMask, shadowsExtraThickMask) //! this is set from indicators when they need extra thickness mask size readonly property int indicatorsExtraThickMask: indicators.info.extraMaskThickness property int shadowsExtraThickMask: { if (LatteCore.WindowSystem.isPlatformWayland) { return 0; } //! 45% of max shadow size in px. var shadowMaxNeededMargin = 0.45 * root.appShadowSizeOriginal; var shadowOpacity = (plasmoid.configuration.shadowOpacity) / 100; //! +40% of shadow opacity in percentage shadowOpacity = shadowOpacity + shadowOpacity*0.4; //! This way we are trying to calculate how many pixels are needed in order for the shadow //! to be drawn correctly without being cut of from View::mask() under X11 shadowMaxNeededMargin = (shadowMaxNeededMargin * shadowOpacity); //! give some more space when items shadows are enabled and extremely big if (root.enableShadows && metrics.margin.maxThickness < shadowMaxNeededMargin) { return shadowMaxNeededMargin - metrics.margin.maxThickness; } return 0; } property Item applets: null Binding{ target: latteView property:"maxThickness" //! prevents updating window geometry during closing window in wayland and such fixes a crash when: latteView && !inTempHiding && !inForceHiding && !inScreenEdgeInternalWindowSliding value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessZoomOriginal } property bool validIconSize: (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize) property bool inPublishingState: validIconSize && !inSlidingIn && !inSlidingOut && !inTempHiding && !inForceHiding Binding{ target: latteView property:"normalThickness" when: latteView && inPublishingState value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessNormalOriginal } Binding{ target: latteView property:"editThickness" when: latteView value: thicknessEditMode } Binding { target: latteView property: "headThicknessGap" when: latteView && !root.editMode && !editModeVisual.inEditMode && !inTempHiding && !inForceHiding && !inScreenEdgeInternalWindowSliding && inPublishingState value: { if (root.behaveAsPlasmaPanel || root.viewType === LatteCore.Types.PanelView) { return 0; } return thicknessZoomOriginal - thicknessNormalOriginalValue + extraNormalThickMask;/*extra normal thickness from indicators/applets requirements must be ignored*/ } } Binding{ target: latteView property: "type" when: latteView value: root.viewType } Binding{ target: latteView property: "behaveAsPlasmaPanel" when: latteView value: root.editMode ? false : root.behaveAsPlasmaPanel } Binding{ target: latteView property: "fontPixelSize" when: theme value: theme.defaultFont.pixelSize } Binding{ target: latteView property:"inEditMode" when: latteView value: root.editMode } Binding{ target: latteView property:"latteTasksArePresent" when: latteView value: latteApplet !== null } Binding{ target: latteView property: "maxLength" when: latteView value: maxLengthPerCentage/100 } Binding{ target: latteView property: "offset" when: latteView value: plasmoid.configuration.offset/100 } Binding{ target: latteView property: "screenEdgeMargin" when: latteView value: Math.max(0, plasmoid.configuration.screenEdgeMargin) } Binding{ target: latteView property: "screenEdgeMarginEnabled" when: latteView value: root.screenEdgeMarginEnabled && !root.hideThickScreenGap } Binding{ target: latteView property: "alignment" when: latteView value: root.panelAlignment } Binding{ target: latteView property: "isTouchingTopViewAndIsBusy" when: latteView value: { var isTouchingTopScreenEdge = (latteView.y === latteView.screenGeometry.y); var hasTopBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.TopBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingTopScreenEdge && !hasTopBorder && background.isShown; } } Binding{ target: latteView property: "isTouchingBottomViewAndIsBusy" when: latteView value: { var latteBottom = latteView.y + latteView.height; var screenBottom = latteView.screenGeometry.y + latteView.screenGeometry.height; var isTouchingBottomScreenEdge = (latteBottom === screenBottom); var hasBottomBorder = ((latteView.effects && (latteView.effects.enabledBorders & PlasmaCore.FrameSvg.BottomBorder)) > 0); return root.isVertical && !latteView.visibility.isHidden && !isTouchingBottomScreenEdge && !hasBottomBorder && background.isShown; } } //! View::Effects bindings Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "backgroundOpacity" when: latteView && latteView.effects value: background.currentOpacity } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawEffects" when: latteView && latteView.effects value: LatteCore.WindowSystem.compositingActive && !root.inConfigureAppletsMode && (((root.blurEnabled && root.useThemePanel) || (root.blurEnabled && root.forceSolidPanel && LatteCore.WindowSystem.compositingActive)) && (!root.inStartup || inForceHiding || inTempHiding)) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "drawShadows" when: latteView && latteView.effects value: root.drawShadowsExternal && (!root.inStartup || inForceHiding || inTempHiding) && !(latteView && latteView.visibility.isHidden) } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"editShadow" when: latteView && latteView.effects value: root.editShadow } Binding{ target: latteView && latteView.effects ? latteView.effects : null property:"innerShadow" when: latteView && latteView.effects value: { if (editModeVisual.editAnimationEnded && !root.behaveAsPlasmaPanel) { return root.editShadow; } else { return background.shadows.headThickness; } } } Binding{ target: latteView && latteView.effects ? latteView.effects : null property: "settingsMaskSubtracted" when: latteView && latteView.effects value: { if (LatteCore.WindowSystem.compositingActive && root.editMode && editModeVisual.editAnimationEnded && (animations.needBothAxis.count === 0 || parabolic.factor.maxZoom===1) ) { return true; } else { return false; } } } //! View::Positioner bindings Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnTopEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnTopEdge } Binding{ target: latteView && latteView.positioner ? latteView.positioner : null property: "isStickedOnBottomEdge" when: latteView && latteView.positioner value: plasmoid.configuration.isStickedOnBottomEdge } //! View::WindowsTracker bindings Binding{ target: latteView && latteView.windowsTracker ? latteView.windowsTracker : null property: "enabled" when: latteView && latteView.windowsTracker && latteView.visibility value: (latteView && latteView.visibility && !(latteView.visibility.mode === LatteCore.Types.AlwaysVisible /* Visibility */ || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow || latteView.visibility.mode === LatteCore.Types.AutoHide)) || applets.require.windowsTrackingCount > 0 /*Applets Need Windows Tracking */ || root.dragActiveWindowEnabled /*Dragging Active Window(Empty Areas)*/ || ((root.backgroundOnlyOnMaximized /*Dynamic Background */ || plasmoid.configuration.solidBackgroundForMaximized || root.disablePanelShadowMaximized || root.windowColors !== LatteContainment.Types.NoneWindowColors)) || (root.screenEdgeMarginsEnabled /*Dynamic Screen Edge Margin*/ && plasmoid.configuration.hideScreenGapForMaximized) } Connections{ target:root onEditModeChanged: { if (root.editMode) { visibilityManager.updateMaskArea(); } } } Connections{ target: background.totals onVisualLengthChanged: updateMaskArea(); onVisualThicknessChanged: updateMaskArea(); } Connections{ target: background.shadows onHeadThicknessChanged: updateMaskArea(); } Connections{ target: latteView ? latteView : null onXChanged: updateMaskArea(); onYChanged: updateMaskArea() onWidthChanged: updateMaskArea(); onHeightChanged: updateMaskArea(); } Connections{ target: animations.needBothAxis onCountChanged: updateMaskArea(); } Connections{ target: animations.needLength onCountChanged: updateMaskArea(); } Connections{ target: animations.needThickness onCountChanged: updateMaskArea(); } Connections{ target: layoutsManager onCurrentLayoutIsSwitching: { if (LatteCore.WindowSystem.compositingActive && latteView && latteView.layout && latteView.layout.name === layoutName) { manager.inTempHiding = true; manager.inForceHiding = true; parabolic.sglClearZoom(); manager.slotMustBeHide(); } } } Connections{ target: themeExtended ? themeExtended : null onRoundnessChanged: latteView.effects.forceMaskRedraw(); onThemeChanged: latteView.effects.forceMaskRedraw(); } onMaskIsFloatingChanged: updateMaskArea(); onNormalStateChanged: { if (normalState) { autosize.updateIconSize(); - root.updateSizeForAppletsInFill(); + layouter.updateSizeForAppletsInFill(); } } onThicknessZoomOriginalChanged: updateMaskArea(); function slotContainsMouseChanged() { if(latteView.visibility.containsMouse && latteView.visibility.mode !== LatteCore.Types.SideBar) { updateMaskArea(); if (slidingAnimationAutoHiddenOut.running && !inTempHiding && !inForceHiding) { slotMustBeShown(); } } } function slotMustBeShown() { //! WindowsCanCover case if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnFrontLayer(); return; } //! Normal Dodge/AutoHide case if (!slidingAnimationAutoHiddenIn.running && !inTempHiding && !inForceHiding){ slidingAnimationAutoHiddenIn.init(); } } function slotMustBeHide() { if (latteView && latteView.visibility.mode === LatteCore.Types.WindowsCanCover) { latteView.visibility.setViewOnBackLayer(); return; } //! prevent sliding-in on startup if the dodge modes have sent a hide signal if (inStartupTimer.running && root.inStartup) { root.inStartup = false; } //! Normal Dodge/AutoHide case if((!slidingAnimationAutoHiddenOut.running && !latteView.visibility.blockHiding && (!latteView.visibility.containsMouse || latteView.visibility.mode === LatteCore.Types.SideBar)) || inForceHiding) { slidingAnimationAutoHiddenOut.init(); } } //! functions used for sliding out/in during location/screen changes function slotHideDockDuringLocationChange() { inTempHiding = true; blockUpdateMask = true; if(!slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.init(); } } function slotShowDockAfterLocationChange() { slidingAnimationAutoHiddenIn.init(); } function sendHideDockDuringLocationChangeFinished(){ blockUpdateMask = false; latteView.positioner.hideDockDuringLocationChangeFinished(); } function sendSlidingOutAnimationEnded() { latteView.visibility.hide(); latteView.visibility.isHidden = true; if (visibilityManager.debugManager) { console.log("hiding animation ended..."); } sendHideDockDuringLocationChangeFinished(); } ///test maskArea function updateMaskArea() { if (!latteView || blockUpdateMask) { return; } var localX = 0; var localY = 0; normalState = ((animations.needBothAxis.count === 0) && (animations.needLength.count === 0)) || (latteView.visibility.isHidden && !latteView.visibility.containsMouse && animations.needThickness.count === 0); // debug maskArea criteria if (debugManager) { console.log(animations.needBothAxis.count + ", " + animations.needLength.count + ", " + animations.needThickness.count + ", " + latteView.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 noCompositingEdit = !LatteCore.WindowSystem.compositingActive && root.editMode; if (LatteCore.WindowSystem.compositingActive || noCompositingEdit) { if (normalState) { //console.log("entered normal state..."); //count panel length //used when !compositing and in editMode if (noCompositingEdit) { tempLength = root.isHorizontal ? root.width : root.height; } else { tempLength = background.totals.visualLength; } tempThickness = thicknessNormal; if (animations.needThickness.count > 0) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessZoom : thicknessNormal; } if (maskIsFloating) { tempThickness = tempThickness - maskFloatedGap; } if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } //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) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = latteView.height + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = latteView.height - tempThickness - maskFloatedGap; } else { localY = latteView.height - tempThickness; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localY = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localY = maskFloatedGap; } else { localY = 0; } } if (noCompositingEdit) { localX = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localX = (latteView.width/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Left) { localX = background.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localX = (latteView.width/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Right) { localX = latteView.width - tempLength - background.offset; } } else if ((plasmoid.location === PlasmaCore.Types.LeftEdge) || (plasmoid.location === PlasmaCore.Types.RightEdge)){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = -tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = maskFloatedGap; } else { localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (latteView.visibility.isHidden && latteView.visibility.supportsKWinEdges) { localX = latteView.width + tempThickness; } else if (maskIsFloating && !latteView.visibility.isHidden) { localX = latteView.width - tempThickness - maskFloatedGap; } else { localX = latteView.width - tempThickness; } } if (noCompositingEdit) { localY = 0; } else if (plasmoid.configuration.alignment === LatteCore.Types.Justify) { localY = (latteView.height/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Top) { localY = background.offset; } else if (root.panelAlignment === LatteCore.Types.Center) { localY = (latteView.height/2) - tempLength/2 + background.offset; } else if (root.panelAlignment === LatteCore.Types.Bottom) { localY = latteView.height - tempLength - background.offset; } } if (latteView.visibility.isHidden && latteView && latteView.visibility.mode === LatteCore.Types.SideBar) { //!hide completely localX = -1; localY = -1; tempThickness = 1; tempLength = 1; } } else { // !inNormalState if(root.isHorizontal) tempLength = Screen.width; //screenGeometry.width; else tempLength = Screen.height; //screenGeometry.height; //grow only on length and not thickness var onlyLengthAnimation = (animations.needLength.count>0 && animations.needBothAxis.count === 0); if(onlyLengthAnimation) { //this is used to fix a bug with shadow showing when the animation of edit mode //is triggered tempThickness = editModeVisual.editAnimationEnded ? thicknessEditMode + root.editShadow : thicknessEditMode if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } else if (animations.needThickness.count > 0) { tempThickness = thicknessZoomOriginal; } } else{ //use all thickness space if (latteView.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = LatteCore.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else { tempThickness = !maskIsFloating ? thicknessZoomOriginal : thicknessZoomOriginal - maskFloatedGap; } } //configure the x,y position based on thickness if(plasmoid.location === PlasmaCore.Types.RightEdge) { localX = !maskIsFloating ? latteView.width - tempThickness : latteView.width - tempThickness - maskFloatedGap; if (localX < 0) { tempThickness = tempThickness + localX; localX = 0; } } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localY = !maskIsFloating ? latteView.height - tempThickness : latteView.height - tempThickness - maskFloatedGap; if (localY < 0) { tempThickness = tempThickness + localY; localY = 0; } } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localY = !maskIsFloating ? 0 : maskFloatedGap; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = !maskIsFloating ? 0 : maskFloatedGap; } } } // end of compositing calculations var maskArea = latteView.effects.mask; if (LatteCore.WindowSystem.compositingActive) { var maskLength = maskArea.width; //in Horizontal if (root.isVertical) { maskLength = maskArea.height; } var maskThickness = maskArea.height; //in Horizontal if (root.isVertical) { maskThickness = maskArea.width; } } else if (!noCompositingEdit){ //! no compositing case var overridesHidden = latteView.visibility.isHidden && !latteView.visibility.supportsKWinEdges; if (!overridesHidden) { localX = latteView.effects.rect.x; localY = latteView.effects.rect.y; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localX = latteView.effects.rect.x; localY = root.height - thicknessAutoHidden; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localX = latteView.effects.rect.x; localY = 0; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = 0; localY = latteView.effects.rect.y; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localX = root.width - thicknessAutoHidden; localY = latteView.effects.rect.y; } } if (root.isHorizontal) { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.height; tempLength = latteView.effects.rect.width; } else { tempThickness = overridesHidden ? thicknessAutoHidden : latteView.effects.rect.width; tempLength = latteView.effects.rect.height; } } // 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 (!LatteCore.WindowSystem.compositingActive) { latteView.effects.mask = newMaskArea; } else { if (latteView.behaveAsPlasmaPanel && !root.editMode) { latteView.effects.mask = Qt.rect(0,0,root.width,root.height); } else { latteView.effects.mask = newMaskArea; } } } var validIconSize = (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === autosize.iconSize); //console.log("reached updating geometry ::: "+dock.maskArea); if(inPublishingState && !latteView.visibility.isHidden && (normalState || root.editMode)) { //! Important: Local Geometry must not be updated when view ISHIDDEN //! because it breaks Dodge(s) modes in such case var localGeometry = Qt.rect(0, 0, root.width, root.height); //the shadows size must be removed from the maskArea //before updating the localDockGeometry if (!latteView.behaveAsPlasmaPanel || root.editMode) { var cleanThickness = metrics.totals.thickness; var edgeMargin = finalScreenEdgeMargin; if (plasmoid.location === PlasmaCore.Types.TopEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = edgeMargin; localGeometry.height = cleanThickness ; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localGeometry.x = latteView.effects.rect.x; // from effects area localGeometry.width = latteView.effects.rect.width; // from effects area localGeometry.y = root.height - cleanThickness - edgeMargin; localGeometry.height = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = edgeMargin; localGeometry.width = cleanThickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localGeometry.y = latteView.effects.rect.y; // from effects area localGeometry.height = latteView.effects.rect.height; // from effects area localGeometry.x = root.width - cleanThickness - edgeMargin; localGeometry.width = cleanThickness; } //set the boundaries for latteView local geometry //qBound = qMax(min, qMin(value, max)). localGeometry.x = Math.max(0, Math.min(localGeometry.x, latteView.width)); localGeometry.y = Math.max(0, Math.min(localGeometry.y, latteView.height)); localGeometry.width = Math.min(localGeometry.width, latteView.width); localGeometry.height = Math.min(localGeometry.height, latteView.height); } //console.log("update geometry ::: "+localGeometry); latteView.localGeometry = localGeometry; } } 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: latteView ? latteView.effects.mask.x : -1 y: latteView ? latteView.effects.mask.y : -1 height: latteView ? latteView.effects.mask.height : 0 width: latteView ? latteView.effects.mask.width : 0 border.color: "green" border.width: 1 color: "transparent" } } } /***Hiding/Showing Animations*****/ //////////////// Animations - Slide In - Out SequentialAnimation{ id: slidingAnimationAutoHiddenOut ScriptAction{ script: { root.isHalfShown = true; } } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: { if (root.behaveAsPlasmaPanel) { return slidingOutToPos; } if (LatteCore.WindowSystem.compositingActive) { return slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return slidingOutToPos + 1; } else { return slidingOutToPos - 1; } } } duration: manager.animationSpeed easing.type: Easing.InQuad } ScriptAction{ script: { latteView.visibility.isHidden = true; if (root.behaveAsPlasmaPanel && latteView.positioner.slideOffset !== 0) { //! hide real panels when they slide-out latteView.visibility.hide(); } } } onStarted: { if (manager.debugManager) { console.log("hiding animation started..."); } } onStopped: { //! Trying to move the ending part of the signals at the end of editing animation if (!manager.inTempHiding) { manager.updateMaskArea(); } else { if (!editModeVisual.inEditMode) { manager.sendSlidingOutAnimationEnded(); } } latteView.visibility.slideOutFinished(); } function init() { if (manager.inLocationAnimation || !latteView.visibility.blockHiding) { start(); } } } SequentialAnimation{ id: slidingAnimationAutoHiddenIn PauseAnimation{ duration: manager.inTempHiding && animations.active ? 500 : 0 } PropertyAnimation { target: !root.behaveAsPlasmaPanel ? layoutsContainer : latteView.positioner property: !root.behaveAsPlasmaPanel ? (root.isVertical ? "x" : "y") : "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } ScriptAction{ script: { root.isHalfShown = false; root.inStartup = false; } } onStarted: { latteView.visibility.show(); if (manager.debugManager) { console.log("showing animation started..."); } } onStopped: { inSlidingIn = false; if (manager.inTempHiding) { manager.inTempHiding = false; autosize.updateIconSize(); } manager.inTempHiding = false; autosize.updateIconSize(); if (manager.debugManager) { console.log("showing animation ended..."); } latteView.visibility.slideInFinished(); //! this is needed in order to update dock absolute geometry correctly in the end AND //! when a floating dock is sliding-in through masking techniques updateMaskArea(); } function init() { inSlidingIn = true; if (slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.stop(); } latteView.visibility.isHidden = false; updateMaskArea(); start(); } } //! Slides Animations for FLOATING+BEHAVEASPLASMAPANEL when //! HIDETHICKSCREENCAP dynamically is enabled/disabled SequentialAnimation{ id: slidingInRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } } SequentialAnimation{ id: slidingOutRealFloating PropertyAnimation { target: latteView.positioner property: "slideOffset" to: plasmoid.configuration.screenEdgeMargin duration: manager.animationSpeed easing.type: Easing.InQuad } } Connections { target: root onHideThickScreenGapChanged: { if (root.behaveAsPlasmaPanel && !latteView.visibility.isHidden && !inSlidingIn && !inSlidingOut && !inStartup) { if (hideThickScreenGap) { latteView.positioner.inSlideAnimation = true; slidingInRealFloating.stop(); slidingOutRealFloating.start(); } else { slidingOutRealFloating.stop(); slidingInRealFloating.start(); latteView.positioner.inSlideAnimation = false; } } } } } diff --git a/containment/package/contents/ui/abilities/Animations.qml b/containment/package/contents/ui/abilities/Animations.qml index 16f98be0..9441c916 100644 --- a/containment/package/contents/ui/abilities/Animations.qml +++ b/containment/package/contents/ui/abilities/Animations.qml @@ -1,75 +1,66 @@ /* * Copyright 2020 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.7 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.abilities.containers 0.1 as ContainerAbility ContainerAbility.Animations { property Item metrics: null property QtObject settings: null - //TO BE MOVED in LAYOUTER ability - property bool appletsInParentChange: false - readonly property bool inNormalFillCalculationsState: needBothAxis.count === 0 - && needThickness.count === 0 - && ((needLength.count === 0) - || (needLength.count===1 && editModeVisual.inEditMode)) - && (!dragOverlay || (dragOverlay && !dragOverlay.pressed)) /*do not update during moving/dragging applets*/ - && !appletsInParentChange - //! Public Properties active: plasmoid.configuration.animationsEnabled && LatteCore.WindowSystem.compositingActive duration.large: LatteCore.Environment.longDuration duration.proposed: speedFactor.current * 2.8 * duration.large duration.small: LatteCore.Environment.shortDuration speedFactor.normal: 1.0 speedFactor.current: { if (!active || plasmoid.configuration.durationTime === 0) { return 0; } if (plasmoid.configuration.durationTime === 1 ) { return 0.75; } else if (plasmoid.configuration.durationTime === 2) { return speedFactor.normal; } else if (plasmoid.configuration.durationTime === 3) { return 1.15; } return speedFactor.normal; } //! animations related to parabolic effect hoverPixelSensitivity: { if (!settings || settings.sensitivity === LatteApp.Settings.HighMouseSensitivity) { return 1; } else if (settings.sensitivity === LatteApp.Settings.MediumMouseSensitivity) { return Math.max(3, metrics.iconSize / 18); } else if (settings.sensitivity === LatteApp.Settings.LowMouseSensitivity) { return Math.max(5, metrics.iconSize / 10); } } } diff --git a/containment/package/contents/ui/abilities/AutoSize.qml b/containment/package/contents/ui/abilities/AutoSize.qml index 7f0055e7..c1bace12 100644 --- a/containment/package/contents/ui/abilities/AutoSize.qml +++ b/containment/package/contents/ui/abilities/AutoSize.qml @@ -1,248 +1,249 @@ /* * Copyright 2019 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.8 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore Item { id: sizer // when there are only plasma style task managers OR any applets that fill width or height // the automatic icon size algorithm should better be disabled readonly property bool isActive: plasmoid.configuration.autoSizeEnabled && !root.containsOnlyPlasmaTasks - && layouts.fillApplets<=0 + && layouter.fillApplets<=0 && latteView && latteView.visibility.mode !== LatteCore.Types.SideBar property int iconSize: -1 //it is not set, this is the default readonly property bool inCalculatedIconSize: ((metrics.iconSize === sizer.iconSize) || (metrics.iconSize === metrics.maxIconSize)) readonly property bool inAutoSizeAnimation: !inCalculatedIconSize readonly property int automaticStep: 8 readonly property int historyMaxSize: 10 readonly property int historyMinSize: 4 //! Prediction History of the algorithm in order to track cases where the algorithm produces //! grows and shrinks endlessly property variant history: [] //! required elements property Item layouts + property Item layouter property Item metrics property Item visibility onInAutoSizeAnimationChanged: { if (inAutoSizeAnimation) { animations.needBothAxis.addEvent(sizer); } else { animations.needBothAxis.removeEvent(sizer); } } onIsActiveChanged: clearHistory(); Connections { target: root onContainsOnlyPlasmaTasksChanged: sizer.updateIconSize(); onEditModeChanged: sizer.updateIconSize(); onMaxLengthChanged: { if (root.editMode) { sizer.updateIconSize(); } } } Connections { target: metrics onPortionIconSizeChanged: { if (metrics.portionIconSize!==-1) { sizer.updateIconSize(); } } } Connections { target: latteView onWidthChanged:{ if (root.isHorizontal && metrics.portionIconSize!==-1) { sizer.updateIconSize(); } } onHeightChanged:{ if (root.isVertical && metrics.portionIconSize!==-1) { sizer.updateIconSize(); } } } //! Prediction History Functions function clearHistory() { history.length = 0; } function addPrediction(currentLength, prediction) { history.unshift({current: currentLength, predicted: prediction}); /* console.log(" -- PREDICTION ARRAY -- "); for(var i=0; i historyMaxSize) { history.splice(historyMinSize, history.length - historyMinSize); } } function producesEndlessLoop(currentLength, prediction) { if (history.length < 2) { return false; } if (history[1].current === currentLength && history[1].predicted === prediction) { //! the current prediction is the same like two steps before in prediction history if(history[0].current > history[0].predicted && history[1].current < history[1].predicted) { //! case2: the algorithm that is trying to SHRINK has already produced same results subsequently console.log(" AUTOMATIC ITEM SIZE PROTECTOR, :: ENDLESS AUTOMATIC SIZE LOOP DETECTED"); return true; } } return false; } function updateIconSize() { if ( !doubleCallAutomaticUpdateIconSize.running && !visibility.inTempHiding && ((visibility.normalState || root.editMode) && (sizer.isActive || (!sizer.isActive && metrics.iconSize!==metrics.maxIconSize))) && (metrics.iconSize===metrics.maxIconSize || metrics.iconSize === sizer.iconSize) ) { //!doubler timer if (!doubleCallAutomaticUpdateIconSize.secondTimeCallApplied) { doubleCallAutomaticUpdateIconSize.start(); } else { doubleCallAutomaticUpdateIconSize.secondTimeCallApplied = false; } var layoutLength; var maxLength = root.maxLength; //console.log("------Entered check-----"); //console.log("max length: "+ maxLength); if (root.isVertical) { layoutLength = (plasmoid.configuration.alignment === LatteCore.Types.Justify) ? layouts.startLayout.height+layouts.mainLayout.height+layouts.endLayout.height : layouts.mainLayout.height } else { layoutLength = (plasmoid.configuration.alignment === LatteCore.Types.Justify) ? layouts.startLayout.width+layouts.mainLayout.width+layouts.endLayout.width : layouts.mainLayout.width } var itemLength = metrics.totals.length; var toShrinkLimit = maxLength - (parabolic.factor.zoom * itemLength); //! to grow limit must be a little less than the shrink one in order to be more robust and //! not create endless loops from early calculations var toGrowLimit = maxLength - (1.2 * parabolic.factor.zoom * itemLength); //console.log("toShrinkLimit: "+ toShrinkLimit); //console.log("toGrowLimit: "+ toGrowLimit); var newIconSizeFound = false; if (layoutLength > toShrinkLimit) { //must shrink // console.log("step3"); var nextIconSize = metrics.maxIconSize; do { nextIconSize = nextIconSize - automaticStep; var factor = nextIconSize / metrics.iconSize; var nextLength = factor * layoutLength; } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); var intLength = Math.round(layoutLength); var intNextLength = Math.round(nextLength); iconSize = nextIconSize; newIconSizeFound = true; addPrediction(intLength, intNextLength); // console.log("Step 3 - found:"+iconSize); } else if ((layoutLength 0 && !producesEndlessLoop(intLength2, intNextLength2)) { if (foundGoodSize === metrics.maxIconSize) { iconSize = -1; } else { iconSize = foundGoodSize; } newIconSizeFound = true addPrediction(intLength2, intNextLength2); // console.log("Step 4 - found:"+iconSize); } else { // console.log("Step 4 - did not found..."); } } } } //! This functions makes sure to call the updateIconSize(); function which is costly //! one more time after its last call to confirm the applied icon size found Timer{ id:doubleCallAutomaticUpdateIconSize interval: 1000 property bool secondTimeCallApplied: false onTriggered: { if (!secondTimeCallApplied) { secondTimeCallApplied = true; sizer.updateIconSize(); } } } } diff --git a/containment/package/contents/ui/abilities/Indexer.qml b/containment/package/contents/ui/abilities/Indexer.qml index 06f8bb2e..dac2c32e 100644 --- a/containment/package/contents/ui/abilities/Indexer.qml +++ b/containment/package/contents/ui/abilities/Indexer.qml @@ -1,45 +1,45 @@ /* * Copyright 2020 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.7 import org.kde.plasma.plasmoid 2.0 import "./privates" as Ability Ability.IndexerPrivate { //! do not update during dragging/moving applets inConfigureAppletsMode updateIsBlocked: (root.dragOverlay && root.dragOverlay.pressed) - || animations.appletsInParentChange + || layouter.appletsInParentChange function getClientBridge(index) { if (clientsBridges.length<=0) { return false; } var ibl = clientsBridges.length; for(var i=0; i +* +* 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.7 +import org.kde.plasma.plasmoid 2.0 + +import "./privates" as Ability + +Ability.LayouterPrivate { + id: _layouter + + property bool appletsInParentChange: false + + readonly property bool inNormalFillCalculationsState: animations.needBothAxis.count === 0 + && animations.needThickness.count === 0 + && ((animations.needLength.count === 0) + || (animations.needLength.count===1 && editModeVisual.inEditMode)) + && (!dragOverlay || (dragOverlay && !dragOverlay.pressed)) /*do not update during moving/dragging applets*/ + && !appletsInParentChange + + + function updateSizeForAppletsInFill() { + if (!updateSizeForAppletsInFillTimer.running) { + _layouter._updateSizeForAppletsInFill(); + updateSizeForAppletsInFillTimer.start(); + } + } + + onInNormalFillCalculationsStateChanged: { + if (inNormalFillCalculationsState) { + _layouter.updateSizeForAppletsInFill(); + } + } + + Connections { + target: layouts + onContentsLengthChanged: _layouter.updateSizeForAppletsInFill(); + + } + + //! This timer is needed in order to reduce the calls to heavy cpu function + //! updateSizeForAppletsInFill() + Timer{ + id: updateSizeForAppletsInFillTimer + interval: 50 + onTriggered: _layouter._updateSizeForAppletsInFill(); + } +} diff --git a/containment/package/contents/ui/abilities/privates/LayouterPrivate.qml b/containment/package/contents/ui/abilities/privates/LayouterPrivate.qml new file mode 100644 index 00000000..c4a14b74 --- /dev/null +++ b/containment/package/contents/ui/abilities/privates/LayouterPrivate.qml @@ -0,0 +1,363 @@ +/* +* Copyright 2020 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.7 +import org.kde.plasma.plasmoid 2.0 + +import org.kde.latte.core 0.2 as LatteCore + +import "./layouter" as LayouterElements + +Item { + property Item layouts: null + property Item animations: null + property Item indexer: null + + readonly property int fillApplets: startLayout.fillApplets + mainLayout.fillApplets + endLayout.fillApplets + + readonly property Item startLayout: LayouterElements.AppletsContainer { + grid: layouts.startLayout + } + + readonly property Item mainLayout: LayouterElements.AppletsContainer { + grid: layouts.mainLayout + } + + readonly property Item endLayout: LayouterElements.AppletsContainer { + grid: layouts.endLayout + } + + //! FILLWIDTH/FILLHEIGHT COMPUTATIONS + //! Computations in order to calculate correctly the sizes for applets + //! that are requesting fillWidth or fillHeight + + //! qBound style function that is specialized in Layouts + //! meaning that -1 values are ignored for fillWidth(s)/Height(s) + function layoutBound(min, pref, max){ + if (max === -1) { + max = pref === -1 ? min : pref; + } + + if (pref === -1) { + pref = max === -1 ? min : pref; + } + + return Math.min(Math.max(min,pref),max); + } + + + //! initialize AppletItems flag "inFillCalculations" in order + //! to inform them that new calculations are taking place + function initLayoutForFillsCalculations(layout) { + for(var i=0; i=0 && minSize!==Infinity ? minSize : -1; + prefSize = minSize>=0 && prefSize!==Infinity ? prefSize : -1; + maxSize = maxSize>=0 && maxSize!== Infinity ? maxSize : -1; + + var appliedSize = -1; + + //! check if the applet does not provide any valid metrics and for that case + //! the system must decide what space to be given after the applets that provide + //! nice metrics are assigned their sizes + var systemDecide = ((minSize<0) && (prefSize<0) && (maxSize<0)); + + if (!systemDecide) { + if (noOfApplets>1) { + appliedSize = layoutBound(minSize, prefSize, maxSize); + + // console.log( " s3_1 " + curApplet.applet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); + } else if (noOfApplets===1) { + //! at this step if only one applet has remained for which the max size is not null, + //! then for this applet we make sure the maximum size does not exceed the available space + //! in order for the applet to not be drawn outside the boundaries + appliedSize = layoutBound(minSize, prefSize, Math.min(maxSize, sizePerApplet)); + + // console.log( " s3_2 " + curApplet.applet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); + } + + //! appliedSize is valid and is also lower than the availableSpace, if it is not lower then + //! for this applet the needed space will be provided as a second pass in a fair way + //! between all remained applets that did not gain a valid fill space + if (appliedSize>=0 && appliedSize<=sizePerApplet) { + var properSize = Math.min(appliedSize, availableSpace); + var thickness = root.isVertical ? root.width : root.height; + var adjustedSize = curApplet.isHidden ? 0 : Math.max(thickness, properSize); + + curApplet.sizeForFill = adjustedSize; + curApplet.inFillCalculations = false; + availableSpace = Math.max(0, availableSpace - curApplet.sizeForFill); + noOfApplets = noOfApplets - 1; + sizePerApplet = noOfApplets > 1 ? Math.floor(availableSpace / noOfApplets) : availableSpace; + + // console.log( " s3_3 " + curApplet.applet.pluginName + " assigned: " + curApplet.sizeForFill); + } + } + + // console.log("s3_r " +curApplet.applet.pluginName + " : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets + "\n"); + } + } + } + + return [availableSpace, sizePerApplet, noOfApplets]; + } + + //! during step2/pass2 all the applets with fills + //! that remained with no computations from pass1 + //! are updated with the algorithm's proposed size + function computeStep2ForLayout(layout, sizePerApplet, noOfApplets) { + if (sizePerApplet>0) { + if (noOfApplets === 0) { + //! when all applets have assigned some size and there is still free space, we must find + //! the most demanding space applet and assign the remaining space to it + + var mostDemandingAppletSize = 0; + var mostDemandingApplet = undefined; + + //! applets with no strong opinion + var neutralAppletsNo = 0; + var neutralApplets = []; + + for(var i=0; imostDemandingAppletSize) { + mostDemandingApplet = curApplet; + mostDemandingAppletSize = curApplet.sizeForFill; + } else if (isNeutral) { + neutralAppletsNo = neutralAppletsNo + 1; + neutralApplets.push(curApplet); + } + } + } + + if (mostDemandingApplet) { + //! the most demanding applet gains all the remaining space + mostDemandingApplet.sizeForFill = mostDemandingApplet.sizeForFill + sizePerApplet; + + // console.log("s4_1 "+ mostDemandingApplet.applet.pluginName + " assigned: " + mostDemandingApplet.sizeForFill + "\n"); + } else if (neutralAppletsNo>0) { + //! if no demanding applets was found then the available space is splitted equally + //! between all neutralApplets + var adjustedAppletSize = (sizePerApplet / neutralAppletsNo); + for (var j=0; jNo values. For step2 passing value!=0 + //! means default step2 behavior BUT value=0 means that remained space + //! must be also assigned at the end. + var remainedSpace = (noA === 0 && sizePerApplet > 0) ? true : false + + var startNo = -1; + var mainNo = -1; + var endNo = -1; + + if (remainedSpace) { + if (startLayout.fillApplets > 0) { + startNo = 0; + } else if (lendLayout.fillApplets > 0) { + endNo = 0; + } else if (mainLayout.fillApplets > 0) { + mainNo = 0; + } + } + + //! second pass in order to update sizes for applet that want to fill space + //! these applets get the direct division of the available free space that + //! remained from step1 OR the the free available space that no applet requested yet + + computeStep2ForLayout(startLayout.grid, sizePerApplet, startNo); //default behavior + computeStep2ForLayout(mainLayout.grid, sizePerApplet, mainNo); //default behavior + computeStep2ForLayout(endLayout.grid, sizePerApplet, endNo); //default behavior + + //console.log("s5..."); + } else { + //! Justify mode in all remaining cases + + // console.log(" S3 _ SIZES ::: " + root.maxLength + " ___ " + startLayout.sizeWithNoFillApplets + " ___ " + mainLayout.sizeWithNoFillApplets + " ___ " + endLayout.sizeWithNoFillApplets); + + //! compute the two free spaces around the centered layout + //! they are called start and end accordingly + var halfMainLayout = mainLayout.sizeWithNoFillApplets / 2; + var availableSpaceStart = Math.max(0, root.maxLength/2 - startLayout.sizeWithNoFillApplets - halfMainLayout - root.panelEdgeSpacing/2); + var availableSpaceEnd = Math.max(0, root.maxLength/2 - endLayout.sizeWithNoFillApplets - halfMainLayout - root.panelEdgeSpacing/2); + var availableSpace = availableSpaceStart + availableSpaceEnd - mainLayout.sizeWithNoFillApplets; + + var sizePerAppletMain = mainLayout.fillApplets > 0 ? availableSpace / noA : 0 ; + + var noStart = startLayout.fillApplets; + var noMain = mainLayout.fillApplets; + var noEnd = endLayout.fillApplets; + + //! initialize the computations + initLayoutForFillsCalculations(startLayout.grid); + initLayoutForFillsCalculations(mainLayout.grid); + initLayoutForFillsCalculations(endLayout.grid); + + var res; + + //! first pass + if (mainLayout.fillApplets > 0){ + res = computeStep1ForLayout(mainLayout.grid, availableSpace, sizePerAppletMain, noMain); + sizePerAppletMain = res[1]; noMain = res[2]; + var dif = (availableSpace - res[0]) / 2; + availableSpaceStart = availableSpaceStart - dif; + availableSpaceEnd = availableSpaceEnd - dif; + } + + var sizePerAppletStart = startLayout.fillApplets > 0 ? availableSpaceStart / noStart : 0 ; + var sizePerAppletEnd = endLayout.fillApplets > 0 ? availableSpaceEnd / noEnd : 0 ; + + if (startLayout.fillApplets > 0) { + res = computeStep1ForLayout(startLayout.grid, availableSpaceStart, sizePerAppletStart, noStart); + availableSpaceStart = res[0]; sizePerAppletStart = res[1]; noStart = res[2]; + } + if (endLayout.fillApplets > 0) { + res = computeStep1ForLayout(endLayout.grid, availableSpaceEnd, sizePerAppletEnd, noEnd); + availableSpaceEnd = res[0]; sizePerAppletEnd = res[1]; noEnd = res[2]; + } + + //// + //! second pass + + // console.log(" S ::: " +startLayout.fillApplets + " _ " + sizePerAppletStart + " _ " + noStart); + + if (mainLayout.fillApplets > 0) { + computeStep2ForLayout(mainLayout.grid, sizePerAppletMain, noMain); //default behavior + } + + if (startLayout.fillApplets > 0) { + computeStep2ForLayout(startLayout.grid, sizePerAppletStart, noStart); + } + + if (endLayout.fillApplets > 0) { + computeStep2ForLayout(endLayout.grid, sizePerAppletEnd, noEnd); + } + } + } + } +} diff --git a/containment/package/contents/ui/abilities/privates/layouter/AppletsContainer.qml b/containment/package/contents/ui/abilities/privates/layouter/AppletsContainer.qml new file mode 100644 index 00000000..3d0cd4c9 --- /dev/null +++ b/containment/package/contents/ui/abilities/privates/layouter/AppletsContainer.qml @@ -0,0 +1,155 @@ +/* +* Copyright 2020 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.7 + +Item { + id: appletsContainer + + property Item grid: null + + // items in grid + readonly property int count: grid.children.length + + //it is used in calculations for fillWidth,fillHeight applets + property int shownApplets: 0 + property int fillApplets: 0 + + //it is used in calculations for fillWidth,fillHeight applets + property int sizeWithNoFillApplets: 0 + + readonly property int maxIndex: 99999 + property int firstVisibleIndex: -1 + property int lastVisibleIndex: -1 + + //! do not update during dragging/moving applets inConfigureAppletsMode + readonly property bool updateIsBlocked: (root.dragOverlay && root.dragOverlay.pressed) || appletsInParentChange + + Binding{ + target: appletsContainer + property:"sizeWithNoFillApplets" + when: appletsContainer && grid && !updateIsBlocked && inNormalFillCalculationsState + value: { + var space = 0; + for (var i=0; i=0 + && indexer.hidden.indexOf(appletItem.index)<0 + && indexer.separators.indexOf(appletItem.index)<0 + && appletItem.index < ind) { + ind = appletItem.index; + } + } + + return ind === maxIndex ? -1 : ind; + } + } + + Binding{ + target: appletsContainer + property:"lastVisibleIndex" + when: appletsContainer && grid && !updateIsBlocked + value: { + var ind = -1; + for(var i=0; i=0 + && indexer.hidden.indexOf(appletItem.index)<0 + && indexer.separators.indexOf(appletItem.index)<0 + && appletItem.index > ind) { + ind = appletItem.index; + } + } + + return ind; + } + } + + onCountChanged: { + if (root.editMode) { + //! this is mainly used when removing/adding internal view splitters + //! in order to not break the parabolic effect from wrong indexes + root.updateIndexes(); + } + } + + onFillAppletsChanged: layouter.updateSizeForAppletsInFill(); + onShownAppletsChanged: layouter.updateSizeForAppletsInFill(); + onSizeWithNoFillAppletsChanged: { + console.log(sizeWithNoFillApplets) + layouter.updateSizeForAppletsInFill(); + + } +} diff --git a/containment/package/contents/ui/applet/AppletItem.qml b/containment/package/contents/ui/applet/AppletItem.qml index d1d0e134..57f62584 100644 --- a/containment/package/contents/ui/applet/AppletItem.qml +++ b/containment/package/contents/ui/applet/AppletItem.qml @@ -1,1187 +1,1188 @@ /* * 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.7 import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import "colorizer" as Colorizer import "communicator" as Communicator import "indicator" as Indicator import "../debug" as Debug Item { id: appletItem visible: false width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight //any applets that exceed their limits should not take events from their surrounding applets clip: true signal mousePressed(int x, int y, int button); signal mouseReleased(int x, int y, int button); property bool animationsEnabled: true property bool canBeHovered: true property bool canShowAppletNumberBadge: !isSeparator && !isHidden && !isLattePlasmoid && !isSpacer && !isInternalViewSplitter property bool inFillCalculations: false //temp record, is used in calculations for fillWidth,fillHeight applets property bool needsFillSpace: { //fill flag, it is used in calculations for fillWidth,fillHeight applets if (!applet || !applet.Layout) return false; if (((root.isHorizontal && applet.Layout.fillWidth===true) || (root.isVertical && applet.Layout.fillHeight===true)) && (applet.status !== PlasmaCore.Types.HiddenStatus)) return true; else return false; } property bool userBlocksColorizing: false property bool appletBlocksColorizing: !communicator.requires.latteSideColoringEnabled property bool appletBlocksParabolicEffect: communicator.requires.parabolicEffectLocked property bool lockZoom: false property bool isActive: (isExpanded && applet.pluginName !== root.plasmoidName && applet.pluginName !== "org.kde.activeWindowControl" && applet.pluginName !== "org.kde.plasma.appmenu") property bool isExpanded: false property bool isHidden: (applet && applet.status === PlasmaCore.Types.HiddenStatus) || (isInternalViewSplitter && !root.inConfigureAppletsMode) property bool isInternalViewSplitter: (internalSplitterId > 0) property bool isLattePlasmoid: latteApplet !== null property bool isZoomed: false property bool isSeparator: applet && (applet.pluginName === "audoban.applet.separator" || applet.pluginName === "org.kde.latte.separator") property bool isSpacer: applet && (applet.pluginName === "org.kde.latte.spacer") property bool isSystray: applet && (applet.pluginName === "org.kde.plasma.systemtray" || applet.pluginName === "org.nomad.systemtray" ) - property bool firstChildOfStartLayout: index === layoutsContainer.startLayout.firstVisibleIndex - property bool firstChildOfMainLayout: index === layoutsContainer.mainLayout.firstVisibleIndex - property bool lastChildOfMainLayout: index === layoutsContainer.mainLayout.lastVisibleIndex - property bool lastChildOfEndLayout: index === layoutsContainer.endLayout.lastVisibleIndex + property bool firstChildOfStartLayout: index === appletItem.layouter.startLayout.firstVisibleIndex + property bool firstChildOfMainLayout: index === appletItem.layouter.mainLayout.firstVisibleIndex + property bool lastChildOfMainLayout: index === appletItem.layouter.mainLayout.lastVisibleIndex + property bool lastChildOfEndLayout: index === appletItem.layouter.endLayout.lastVisibleIndex readonly property bool atScreenEdge: { if (root.panelAlignment !== LatteCore.Types.Justify || root.inConfigureAppletsMode || plasmoid.configuration.offset!==0) { return false; } if (root.panelAlignment === LatteCore.Types.Justify) { //! Justify case if (root.maxLengthPerCentage!==100) { return false; } if (root.isHorizontal) { if (firstChildOfStartLayout) { return latteView && latteView.x === latteView.screenGeometry.x; } else if (lastChildOfEndLayout) { return latteView && ((latteView.x + latteView.width) === (latteView.screenGeometry.x + latteView.screenGeometry.width)); } } else { if (firstChildOfStartLayout) { return latteView && latteView.y === latteView.screenGeometry.y; } else if (lastChildOfEndLayout) { return latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); } } return false; } //! [disabled] because it is probably not needed at all. If in the future there is a report //! describing a case that this would be useful this disablement choice can be rethought /*if (root.panelAlignment === LatteCore.Types.Left) { //! Left case return firstChildOfMainLayout; } else if (root.panelAlignment === LatteCore.Types.Right) { //! Right case return lastChildOfMainLayout } if (root.panelAlignment === LatteCore.Types.Top) { return firstChildOfMainLayout && latteView && latteView.y === latteView.screenGeometry.y; } else if (root.panelAlignment === LatteCore.Types.Bottom) { return lastChildOfMainLayout && latteView && ((latteView.y + latteView.height) === (latteView.screenGeometry.y + latteView.screenGeometry.height)); }*/ return false; } //applet is in starting edge property bool firstAppletInContainer: (index >=0) && - ((index === layoutsContainer.startLayout.firstVisibleIndex) - || (index === layoutsContainer.mainLayout.firstVisibleIndex) - || (index === layoutsContainer.endLayout.firstVisibleIndex)) + ((index === layouter.startLayout.firstVisibleIndex) + || (index === layouter.mainLayout.firstVisibleIndex) + || (index === layouter.endLayout.firstVisibleIndex)) //applet is in ending edge property bool lastAppletInContainer: (index >=0) && - ((index === layoutsContainer.startLayout.lastVisibleIndex) - || (index === layoutsContainer.mainLayout.lastVisibleIndex) - || (index === layoutsContainer.endLayout.lastVisibleIndex)) + ((index === layouter.startLayout.lastVisibleIndex) + || (index === layouter.mainLayout.lastVisibleIndex) + || (index === layouter.endLayout.lastVisibleIndex)) readonly property bool acceptMouseEvents: applet && !isLattePlasmoid && !originalAppletBehavior && !appletItem.isSeparator && !communicator.requires.parabolicEffectLocked readonly property bool originalAppletBehavior: (appletItem.parabolic.factor.zoom === 1 && !lockZoom /*hacky flag to keep Latte behavior*/) || (appletItem.parabolic.factor.zoom>1 && !canBeHovered) || (appletItem.parabolic.factor.zoom>1 && canBeHovered && lockZoom) readonly property bool isSquare: communicator.overlayLatteIconIsActive readonly property bool screenEdgeMarginSupported: communicator.requires.screenEdgeMarginSupported property int animationTime: appletItem.animations.speedFactor.normal * (1.2*appletItem.animations.duration.small) property int index: -1 property int maxWidth: root.isHorizontal ? root.height : root.width property int maxHeight: root.isHorizontal ? root.height : root.width property int internalSplitterId: 0 property int previousIndex: -1 property int sizeForFill: -1 //it is used in calculations for fillWidth,fillHeight applets property int spacersMaxSize: Math.max(0,Math.ceil(0.55 * metrics.iconSize) - metrics.totals.lengthEdges) property int status: applet ? applet.status : -1 //! separators tracking readonly property bool tailAppletIsSeparator: { if (isSeparator || index<0) { return false; } var tail = index - 1; while(tail>=0 && indexer.hidden.indexOf(tail)>=0) { //! when a tail applet contains sub-indexing and does not influence //! tracking is considered hidden tail = tail - 1; } if (tail >= 0 && indexer.clients.indexOf(tail)>=0) { //! tail applet contains items sub-indexing var tailBridge = indexer.getClientBridge(tail); if (tailBridge && tailBridge.client) { return tailBridge.client.lastHeadItemIsSeparator; } } // tail applet is normal return (indexer.separators.indexOf(tail)>=0); } readonly property bool headAppletIsSeparator: { if (isSeparator || index<0) { return false; } var head = index + 1; while(head>=0 && indexer.hidden.indexOf(head)>=0) { //! when a head applet contains sub-indexing and does not influence //! tracking is considered hidden head = head + 1; } if (head >= 0 && indexer.clients.indexOf(head)>=0) { //! head applet contains items sub-indexing var headBridge = indexer.getClientBridge(head); if (headBridge && headBridge.client) { return headBridge.client.firstTailItemIsSeparator; } } // head applet is normal return (indexer.separators.indexOf(head)>=0); } //! local margins readonly property bool parabolicEffectMarginsEnabled: appletItem.parabolic.factor.zoom>1 && !originalAppletBehavior property int lengthAppletPadding: metrics.fraction.lengthAppletPadding === -1 || parabolicEffectMarginsEnabled ? metrics.padding.length : metrics.padding.lengthApplet property int lengthAppletFullMargin: lengthAppletPadding + metrics.margin.length property int lengthAppletFullMargins: 2 * lengthAppletFullMargin property int internalWidthMargins: { if (root.isVertical) { return metrics.totals.thicknessEdges; } /*TODO, Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletPadding + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletPadding; } property int internalHeightMargins: { if (root.isHorizontal) { return root.metrics.totals.thicknessEdges; } /*TODO,Fitt's case: is temporary until the atScreenEdge applets are aligned properly to the corner and the wrapper is taking all the space needed in order to fill right. For atScreenEdge appplets that should be: applet size + lengthAppletPadding + lengthAppletExtMargin. The indicator should follow also the applet alignment in this in order to feel right */ return 2 * lengthAppletPadding; } //! are set by the indicator property int iconOffsetX: 0 property int iconOffsetY: 0 property real computeWidth: root.isVertical ? wrapper.width : hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width property real computeHeight: root.isVertical ? hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height : wrapper.height property string title: isInternalViewSplitter ? "Now Dock Splitter" : "" property Item applet: null property Item latteApplet: applet && (applet.pluginName === root.plasmoidName) ? (applet.children[0] ? applet.children[0] : null) : null property Item latteStyleApplet: applet && ((applet.pluginName === "org.kde.latte.spacer") || (applet.pluginName === "org.kde.latte.separator")) ? (applet.children[0] ? applet.children[0] : null) : null property Item appletWrapper: applet && (applet.pluginName === root.plasmoidName )? wrapper : wrapper.wrapperContainer property Item tooltipVisualParent: titleTooltipParent readonly property alias communicator: _communicator readonly property alias wrapper: _wrapper property Item animations: null property Item indexer: null + property Item layouter: null property Item metrics: null property Item parabolic: null property bool containsMouse: appletMouseArea.containsMouse || (isLattePlasmoid && latteApplet.containsMouse) property bool pressed: viewSignalsConnector.pressed || clickedAnimation.running //// BEGIN :: Animate Applet when a new applet is dragged in the view //when the applet moves caused by its resize, don't animate. //this is completely heuristic, but looks way less "jumpy" property bool movingForResize: false property int oldX: x property int oldY: y onXChanged: { if (root.isVertical) { return; } if (movingForResize) { movingForResize = false; return; } var draggingAppletInConfigure = root.dragOverlay && root.dragOverlay.currentApplet; var isCurrentAppletInDragging = draggingAppletInConfigure && (root.dragOverlay.currentApplet === appletItem); var dropApplet = root.dragInfo.entered && foreDropArea.visible if (isCurrentAppletInDragging || !draggingAppletInConfigure && !dropApplet) { return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } onYChanged: { if (root.isHorizontal) { return; } if (movingForResize) { movingForResize = false; return; } var draggingAppletInConfigure = root.dragOverlay && root.dragOverlay.currentApplet; var isCurrentAppletInDragging = draggingAppletInConfigure && (root.dragOverlay.currentApplet === appletItem); var dropApplet = root.dragInfo.entered && foreDropArea.visible if (isCurrentAppletInDragging || !draggingAppletInConfigure && !dropApplet) { return; } if (!root.isVertical) { translation.x = oldX - x; translation.y = 0; } else { translation.y = oldY - y; translation.x = 0; } translAnim.running = true; if (!root.isVertical) { oldX = x; oldY = 0; } else { oldY = y; oldX = 0; } } transform: Translate { id: translation } NumberAnimation { id: translAnim duration: appletItem.animations.duration.large easing.type: Easing.InOutQuad target: translation properties: "x,y" to: 0 } Behavior on lengthAppletPadding { NumberAnimation { duration: 0.8 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } //// END :: Animate Applet when a new applet is dragged in the view /// BEGIN functions function activateAppletForNeutralAreas(mouse){ //if the event is at the active indicator or spacers area then try to expand the applet, //unfortunately for other applets there is no other way to activate them yet //for example the icon-only applets var choords = mapToItem(appletItem.appletWrapper, mouse.x, mouse.y); var wrapperContainsMouse = choords.x>=0 && choords.y>=0 && choords.x=0 && mouse.y>=0 && mouse.x0); var appletNeutralAreaEnabled = !(inThicknessNeutralArea && root.dragActiveWindowEnabled); if (appletItemContainsMouse && !wrapperContainsMouse && appletNeutralAreaEnabled) { //console.log("PASSED"); latteView.extendedInterface.toggleAppletExpanded(applet.id); } else { //console.log("REJECTED"); } } function checkIndex(){ index = -1; - for(var i=0; i maxSize || applet.Layout.minimumWidth > maxForMinimumSize)) || (applet && root.isVertical && (applet.height > maxSize || applet.Layout.minimumHeight > maxForMinimumSize))) && !appletItem.isSpacer && !communicator.canShowOverlaiedLatteIcon) ) { appletItem.canBeHovered = false; } else { appletItem.canBeHovered = true; } } } function slotDestroyInternalViewSplitters() { if (isInternalViewSplitter) { destroy(); } } //! pos in global root positioning function containsPos(pos) { var relPos = root.mapToItem(appletItem,pos.x, pos.y); if (relPos.x>=0 && relPos.x<=width && relPos.y>=0 && relPos.y<=height) return true; return false; } function refersEntryIndex(entryIndex) { return (entryIndex === parabolicManager.pseudoAppletIndex(appletItem.index)); } ///END functions //BEGIN connections onAppletChanged: { if (!applet) { destroy(); } } onIndexChanged: { if (appletItem.latteApplet) { root.latteAppletPos = index; } if (index>-1) { previousIndex = index; } } onIsExpandedChanged: { if (isExpanded) { root.hideTooltipLabel(); } } onIsSystrayChanged: { checkCanBeHovered(); } onLatteAppletChanged: { if(appletItem.latteApplet){ root.latteApplet = appletItem.latteApplet; root.latteAppletContainer = appletItem; root.latteAppletPos = index; appletItem.latteApplet.latteView = root; appletItem.latteApplet.forceHidePanel = true; appletItem.latteApplet.signalPreviewsShown.connect(slotPreviewsShown); } } onNeedsFillSpaceChanged: checkCanBeHovered(); Component.onCompleted: { checkIndex(); root.updateIndexes.connect(checkIndex); root.destroyInternalViewSplitters.connect(slotDestroyInternalViewSplitters); parabolic.sglClearZoom.connect(sltClearZoom); } Component.onDestruction: { appletItem.animations.needBothAxis.removeEvent(appletItem); if(root.latteAppletPos>=0 && root.latteAppletPos === index){ root.latteApplet = null; root.latteAppletContainer = null; root.latteAppletPos = -1; } root.updateIndexes.disconnect(checkIndex); root.destroyInternalViewSplitters.disconnect(slotDestroyInternalViewSplitters); parabolic.sglClearZoom.disconnect(sltClearZoom); if (appletItem.latteApplet) { appletItem.latteApplet.signalPreviewsShown.disconnect(slotPreviewsShown); } } Connections{ target: root onSignalActivateEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.activateTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } onSignalNewInstanceForEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.newInstanceForTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && refersEntryIndex(entryIndex)) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } Connections { id: viewSignalsConnector target: root.latteView ? root.latteView : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden property bool pressed: false property bool blockWheel: false onMousePressed: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = true; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mousePressed(local.x, local.y, button); if (button === Qt.LeftButton) { appletItem.activateAppletForNeutralAreas(local); } } } onMouseReleased: { if (appletItem.containsPos(pos)) { viewSignalsConnector.pressed = false; var local = appletItem.mapFromItem(root, pos.x, pos.y); appletItem.mouseReleased(local.x, local.y, button); } } onWheelScrolled: { if (!appletItem.applet || !root.mouseWheelActions || viewSignalsConnector.blockWheel || (root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)) { return; } blockWheel = true; scrollDelayer.start(); if (appletItem.containsPos(pos) && root.latteView.extendedInterface.appletIsExpandable(applet.id)) { var angle = angleDelta.y / 8; var expanded = root.latteView.extendedInterface.appletIsExpanded(applet.id); if ((angle > 12 && !expanded) /*positive direction*/ || (angle < -12 && expanded) /*negative direction*/) { latteView.extendedInterface.toggleAppletExpanded(applet.id); } } } } Connections { target: root.latteView ? root.latteView.extendedInterface : null enabled: !appletItem.isLattePlasmoid && !appletItem.isSeparator && !appletItem.isSpacer && !appletItem.isHidden onExpandedAppletStateChanged: { if (latteView.extendedInterface.hasExpandedApplet && appletItem.applet) { appletItem.isExpanded = latteView.extendedInterface.appletIsExpandable(appletItem.applet.id) && latteView.extendedInterface.appletIsExpanded(appletItem.applet.id); } else { appletItem.isExpanded = false; } } } ///END connections //! It is used for any communication needed with the underlying applet Communicator.Engine{ id: _communicator //set up the overlayed appletItems and properties for when a overlaiedIconItem must be presented to the user //because the plasma widgets specific implementation breaks the Latte experience onOverlayLatteIconIsActiveChanged:{ if (!overlayLatteIconIsActive && applet.opacity===0) { applet.opacity = 1; wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } else if (overlayLatteIconIsActive && applet.opacity>0) { applet.opacity = 0; if (applet.pluginName === "org.kde.plasma.folder") { applet.parent = wrapper.containerForOverlayIcon; applet.anchors.fill = wrapper.containerForOverlayIcon; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } /* Rectangle{ anchors.fill: parent color: "transparent" border.color: "green" border.width: 1 }*/ /* DEPRECATED in favor of VIEW::MouseSignalsTracking MouseArea{ id: appletMouseAreaBottom anchors.fill: parent propagateComposedEvents: true visible: (!appletMouseArea.visible || !appletMouseArea.enabled) && !root.editMode && !originalAppletBehavior onPressed: { appletItem.activateAppletForNeutralAreas(mouse); mouse.accepted = false; } onReleased: { mouse.accepted = false; } }*/ //! Main Applet Shown Area Flow{ id: appletFlow width: appletItem.computeWidth height: appletItem.computeHeight // a hidden spacer for the first element to add stability // IMPORTANT: hidden spacers must be tested on vertical !!! HiddenSpacer{id: hiddenSpacerLeft} Item { width: wrapper.width height: wrapper.height Indicator.Bridge{ id: indicatorBridge } //! Indicator Back Layer Indicator.Loader{ id: indicatorBackLayer level: Indicator.LevelOptions { id: backLevelOptions isBackground: true bridge: indicatorBridge Binding { target: appletItem property: "iconOffsetX" value: backLevelOptions.requested.iconOffsetX } Binding { target: appletItem property: "iconOffsetY" value: backLevelOptions.requested.iconOffsetY } } } ItemWrapper{ id: _wrapper TitleTooltipParent{ id: titleTooltipParent metrics: appletItem.metrics parabolic: appletItem.parabolic } } //! The Applet Colorizer Colorizer.Applet { id: appletColorizer anchors.fill: parent opacity: mustBeShown ? 1 : 0 readonly property bool mustBeShown: colorizerManager.mustBeShown && !appletItem.userBlocksColorizing && !appletItem.appletBlocksColorizing && !appletItem.isInternalViewSplitter Behavior on opacity { NumberAnimation { duration: 1.2 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } } //! Indicator Front Layer Indicator.Loader{ id: indicatorFrontLayer level: Indicator.LevelOptions { isForeground: true bridge: indicatorBridge } } //! Applet Shortcut Visual Badge Item { id: shortcutBadgeContainer width: { if (root.isHorizontal) { return appletItem.metrics.iconSize * wrapper.zoomScale } else { return badgeThickness; } } height: { if (root.isHorizontal) { return badgeThickness; } else { return appletItem.metrics.iconSize * wrapper.zoomScale } } readonly property int badgeThickness: { if (plasmoid.location === PlasmaCore.Types.BottomEdge || plasmoid.location === PlasmaCore.Types.RightEdge) { return ((appletItem.metrics.iconSize + appletItem.metrics.margin.thickness) * wrapper.zoomScale) + appletItem.metrics.margin.screenEdge; } return ((appletItem.metrics.iconSize + appletItem.metrics.margin.thickness) * wrapper.zoomScale); } ShortcutBadge{ anchors.fill: parent } states:[ State{ name: "horizontal" when: plasmoid.formFactor === PlasmaCore.Types.Horizontal AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } }, State{ name: "vertical" when: plasmoid.formFactor === PlasmaCore.Types.Vertical AnchorChanges{ target: shortcutBadgeContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } } ] } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{id: hiddenSpacerRight; rightSpacer: true} }// Flow with hidden spacers inside //Busy Indicator PlasmaComponents.BusyIndicator { z: 1000 visible: applet && applet.busy running: visible anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width } Loader { id: addingAreaLoader width: root.isHorizontal ? parent.width : parent.width - appletItem.metrics.margin.screenEdge height: root.isHorizontal ? parent.height - appletItem.metrics.margin.screenEdge : parent.height active: isLattePlasmoid sourceComponent: LatteComponents.AddingArea{ id: addingAreaItem anchors.fill: parent // width: root.isHorizontal ? parent.width : parent.width - appletItem.metrics.margin.screenEdge // height: root.isHorizontal ? parent.height - appletItem.metrics.margin.screenEdge : parent.height radius: appletItem.metrics.iconSize/10 opacity: root.addLaunchersMessage ? 1 : 0 backgroundOpacity: 0.75 duration: appletItem.animations.speedFactor.current title: i18n("Tasks Area") } //! AddingAreaItem States states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: appletItem.metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: appletItem.metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: appletItem.metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: addingAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: addingAreaLoader anchors.leftMargin: 0; anchors.rightMargin: appletItem.metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } MouseArea{ id: appletMouseArea anchors.fill: parent enabled: visible hoverEnabled: latteApplet ? false : true propagateComposedEvents: true //! a way must be found in order for this be enabled //! only to support springloading for plasma 5.10 //! also on this is based the tooltips behavior by enabling it //! plasma tooltips are disabled visible: acceptMouseEvents property bool blockWheel: false onEntered: { appletItem.parabolic.stopRestoreZoomTimer(); if (restoreAnimation.running) { restoreAnimation.stop(); } if (!(isSeparator || isSpacer)) { root.showTooltipLabel(appletItem, applet.title); } if (originalAppletBehavior || communicator.requires.parabolicEffectLocked || !canBeHovered) { return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (root.isHorizontal){ layoutsContainer.currentSpot = mouseX; wrapper.calculateScales(mouseX); } else{ layoutsContainer.currentSpot = mouseY; wrapper.calculateScales(mouseY); } } onExited:{ if (communicator.appletIconItemIsShown()) { communicator.setAppletIconItemActive(false); } root.hideTooltipLabel(); if (appletItem.parabolic.factor.zoom>1){ appletItem.parabolic.startRestoreZoomTimer(); } } onPositionChanged: { if (originalAppletBehavior || !canBeHovered) { mouse.accepted = false; return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } var rapidMovement = appletItem.parabolic.lastIndex>=0 && Math.abs(appletItem.parabolic.lastIndex-index)>1; if (rapidMovement) { parabolic.setDirectRenderingEnabled(true); } if( ((wrapper.zoomScale == 1 || wrapper.zoomScale === appletItem.parabolic.factor.zoom) && !parabolic.directRenderingEnabled) || parabolic.directRenderingEnabled) { if (root.isHorizontal){ var step = Math.abs(layoutsContainer.currentSpot-mouse.x); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.x; wrapper.calculateScales(mouse.x); } } else{ var step = Math.abs(layoutsContainer.currentSpot-mouse.y); if (step >= appletItem.animations.hoverPixelSensitivity){ layoutsContainer.currentSpot = mouse.y; wrapper.calculateScales(mouse.y); } } } mouse.accepted = false; } //! these are needed in order for these events to be really forwarded underneath //! otherwise there were applets that did not receive them e.g. lock/logout applet //! when parabolic effect was used onPressed: mouse.accepted = false; onReleased: mouse.accepted = false; } //! Debug Elements Loader{ anchors.bottom: parent.bottom anchors.left: parent.left active: root.debugModeLayouter sourceComponent: Debug.Tag{ label.text: root.isHorizontal ? appletItem.width : appletItem.height label.color: appletItem.needsFillSpace ? "green" : "white" } } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 500 onTriggered: viewSignalsConnector.blockWheel = false; } //BEGIN states states: [ State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined;} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: appletFlow anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined;} } } ] //END states //BEGIN animations ///////Restore Zoom Animation///// ParallelAnimation{ id: restoreAnimation PropertyAnimation { target: wrapper property: "zoomScale" to: 1 duration: 3 * appletItem.animationTime easing.type: Easing.InCubic } } /////Clicked Animation///// SequentialAnimation{ id: clickedAnimation alwaysRunToEnd: true running: appletItem.isSquare && !originalAppletBehavior && appletItem.pressed && (appletItem.animations.speedFactor.current > 0) && !indicators.info.providesClickedAnimation ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: -0.35 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: 0 duration: appletItem.animations.duration.large easing.type: Easing.OutQuad } } } //END animations } diff --git a/containment/package/contents/ui/applet/ItemWrapper.qml b/containment/package/contents/ui/applet/ItemWrapper.qml index 3f196bb6..73019d10 100644 --- a/containment/package/contents/ui/applet/ItemWrapper.qml +++ b/containment/package/contents/ui/applet/ItemWrapper.qml @@ -1,826 +1,826 @@ /* * 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.Layouts 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.latte.core 0.2 as LatteCore import "../../code/MathTools.js" as MathTools Item{ id: wrapper width: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isHorizontal) { return -1; } //! width for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isHorizontal) { if (root.panelAlignment !== LatteCore.Types.Justify) { var maximumValue = (applet.Layout.maximumWidth === Infinity) || applet.Layout.maximumWidth === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumWidth); var constrainedWidth = MathTools.bound(applet.Layout.minimumWidth, applet.Layout.preferredWidth, maximumValue); return root.inConfigureAppletsMode ? Math.max(constrainedWidth, appletItem.metrics.iconSize) : constrainedWidth; } if(appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksWidth; } else { if (root.isHorizontal && root.inConfigureAppletsMode) { return Math.max(Math.min(appletItem.metrics.iconSize, root.minAppletLengthInConfigure), scaledWidth); } return root.isVertical ? scaledWidth + appletItem.metrics.margin.screenEdge : scaledWidth; } } height: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isVertical) { return -1; } //! height for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isVertical) { if (root.panelAlignment !== LatteCore.Types.Justify) { var maximumValue = (applet.Layout.maximumHeight === Infinity) || applet.Layout.maximumHeight === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumHeight); var constrainedHeight = MathTools.bound(applet.Layout.minimumHeight, applet.Layout.preferredHeight, maximumValue); return root.inConfigureAppletsMode ? Math.max(constrainedHeight, appletItem.metrics.iconSize) : constrainedHeight; } if (appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksHeight; } else { if (root.isVertical && root.inConfigureAppletsMode) { return Math.max(Math.min(appletItem.metrics.iconSize, root.minAppletLengthInConfigure), scaledHeight); } return root.isHorizontal ? scaledHeight + appletItem.metrics.margin.screenEdge : scaledHeight; } } opacity: appletColorizer.mustBeShown && graphicsSystem.isAccelerated ? 0 : 1 property bool disableScaleWidth: false property bool disableScaleHeight: false property bool editMode: root.inConfigureAppletsMode property bool edgeLengthMarginsDisabled: isSeparator || !communicator.requires.lengthMarginsEnabled || !canBeHovered property int appletWidth: applet ? applet.width : -1 property int appletHeight: applet ? applet.height : -1 property int appletMinimumWidth: applet && applet.Layout ? applet.Layout.minimumWidth : -1 property int appletMinimumHeight: applet && applet.Layout ? applet.Layout.minimumHeight : -1 property int appletPreferredWidth: applet && applet.Layout ? applet.Layout.preferredWidth : -1 property int appletPreferredHeight: applet && applet.Layout ? applet.Layout.preferredHeight : -1 property int appletMaximumWidth: applet && applet.Layout ? applet.Layout.maximumWidth : -1 property int appletMaximumHeight: applet && applet.Layout ? applet.Layout.maximumHeight : -1 property int iconSize: appletItem.metrics.iconSize property int marginWidth: root.isVertical ? appletItem.metrics.totals.thicknessEdges : (root.inFullJustify && atScreenEdge && !parabolicEffectMarginsEnabled ? edgeLengthMargins : localLengthMargins) //Fitt's Law property int marginHeight: root.isHorizontal ? appletItem.metrics.totals.thicknessEdges : (root.inFullJustify && atScreenEdge && !parabolicEffectMarginsEnabled ? edgeLengthMargins : localLengthMargins) //Fitt's Law property int localLengthMargins: isSeparator || !communicator.requires.lengthMarginsEnabled || isInternalViewSplitter ? 0 : appletItem.lengthAppletFullMargins property int edgeLengthMargins: edgeLengthMarginsDisabled ? 0 : appletItem.lengthAppletPadding * 2 property real scaledWidth: zoomScaleWidth * (layoutWidth + marginWidth) property real scaledHeight: zoomScaleHeight * (layoutHeight + marginHeight) property real zoomScaleWidth: disableScaleWidth ? 1 : zoomScale property real zoomScaleHeight: disableScaleHeight ? 1 : zoomScale property int layoutWidthResult: 0 property int layoutWidth property int layoutHeight property real center:root.isHorizontal ? (width + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 : (height + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 property real zoomScale: 1 property int index: appletItem.index property Item wrapperContainer: _wrapperContainer property Item clickedEffect: _clickedEffect property Item containerForOverlayIcon: _containerForOverlayIcon property Item overlayIconLoader: _overlayIconLoader Behavior on opacity { NumberAnimation { duration: 0.8 * appletItem.animations.duration.proposed easing.type: Easing.OutCubic } } // property int pHeight: applet ? applet.Layout.preferredHeight : -10 /*function debugLayouts(){ if(applet){ console.log("---------- "+ applet.pluginName +" ----------"); console.log("MinW "+applet.Layout.minimumWidth); console.log("PW "+applet.Layout.preferredWidth); console.log("MaxW "+applet.Layout.maximumWidth); console.log("FillW "+applet.Layout.fillWidth); console.log("-----"); console.log("MinH "+applet.Layout.minimumHeight); console.log("PH "+applet.Layout.preferredHeight); console.log("MaxH "+applet.Layout.maximumHeight); console.log("FillH "+applet.Layout.fillHeight); console.log("-----"); console.log("Real Applet Width: "+applet.width); console.log("Real Applet Height: "+applet.height); console.log("-----"); console.log("Real Wrapper Width: "+wrapper.width); console.log("Real Wrapper Height: "+wrapper.height); console.log("-----"); console.log("Can be hovered: " + canBeHovered); console.log("Icon size: " + appletItem.metrics.iconSize); console.log("Thick Margins: " + appletItem.metrics.totals.thicknessEdges); console.log("Intern. Margins: " + (appletItem.metrics.padding.length * 2)); console.log("Intern. Margins: " + (appletItem.metrics.margin.length * 2)); console.log("Max hovered criteria: " + (appletItem.metrics.iconSize + metrics.totals.thicknessEdges)); console.log("-----"); console.log("LayoutW: " + layoutWidth); console.log("LayoutH: " + layoutHeight); } } onLayoutWidthChanged: { debugLayouts(); } onLayoutHeightChanged: { debugLayouts(); }*/ onAppletWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletMinimumWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutWidth(); } onAppletMinimumHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutHeight(); } onAppletPreferredWidthChanged: updateLayoutWidth(); onAppletPreferredHeightChanged: updateLayoutHeight(); onAppletMaximumWidthChanged: updateLayoutWidth(); onAppletMaximumHeightChanged: updateLayoutHeight(); Connections { target: appletItem onCanBeHoveredChanged: { updateLayoutWidth(); updateLayoutHeight(); } } onIconSizeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onEditModeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onZoomScaleChanged: { if ((zoomScale === appletItem.parabolic.factor.zoom) && !appletItem.parabolic.directRenderingEnabled) { appletItem.parabolic.setDirectRenderingEnabled(true); } if ((zoomScale > 1) && !appletItem.isZoomed) { appletItem.isZoomed = true; appletItem.animations.needBothAxis.addEvent(appletItem); } else if (zoomScale == 1) { appletItem.isZoomed = false; appletItem.animations.needBothAxis.removeEvent(appletItem); } } Connections { target: root onIsVerticalChanged: { if (appletItem.latteApplet) { return; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } function updateLayoutHeight(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isVertical) { - layoutsContainer.updateSizeForAppletsInFill(); + appletItem.layouter.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) { layoutHeight = 0; } else { layoutHeight = (root.isHorizontal ? appletItem.metrics.iconSize : Math.min(appletItem.metrics.iconSize, root.maxJustifySplitterSize)); } } else if(appletItem.isSystray && root.isHorizontal){ layoutHeight = appletItem.metrics.iconSize; } else{ if(applet && (applet.Layout.minimumHeight > appletItem.metrics.iconSize) && root.isVertical && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumHeight < appletItem.metrics.iconSize || applet.Layout.preferredHeight > appletItem.metrics.iconSize || appletItem.originalAppletBehavior) && root.isVertical && !disableScaleWidth && !communicator.overlayLatteIconIsActive) { //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumHeight < appletItem.metrics.iconSize)){ layoutHeight = applet.Layout.maximumHeight; } else if (applet.Layout.minimumHeight > appletItem.metrics.iconSize){ blockParabolicEffect = true; layoutHeight = applet.Layout.minimumHeight; } else if ((applet.Layout.preferredHeight > appletItem.metrics.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredHeight > 0 )){ blockParabolicEffect = true; layoutHeight = applet.Layout.preferredHeight; } else{ layoutHeight = appletItem.metrics.iconSize; } } else { layoutHeight = appletItem.metrics.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleHeight = true; } else { disableScaleHeight = false; } } } function updateLayoutWidth(){ appletItem.movingForResize = true; if (appletItem.needsFillSpace && root.isHorizontal) { - layoutsContainer.updateSizeForAppletsInFill(); + appletItem.layouter.updateSizeForAppletsInFill(); return; } var blockParabolicEffect = false; if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.inConfigureAppletsMode) { layoutWidth = 0; } else { layoutWidth = (root.isVertical ? appletItem.metrics.iconSize : Math.min(appletItem.metrics.iconSize, root.maxJustifySplitterSize)); } } else if(appletItem.isSystray && root.isVertical){ layoutWidth = appletItem.metrics.iconSize; } else{ if(applet && (applet.Layout.minimumWidth > appletItem.metrics.iconSize) && root.isHorizontal && !canBeHovered && !communicator.overlayLatteIconIsActive){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumWidth < appletItem.metrics.iconSize || applet.Layout.preferredWidth > appletItem.metrics.iconSize || appletItem.originalAppletBehavior) && root.isHorizontal && !disableScaleHeight && !communicator.overlayLatteIconIsActive){ //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumWidth < appletItem.metrics.iconSize)){ // return applet.Layout.maximumWidth; layoutWidth = applet.Layout.maximumWidth; } else if (applet.Layout.minimumWidth > appletItem.metrics.iconSize){ blockParabolicEffect = true; layoutWidth = applet.Layout.minimumWidth; } else if ((applet.Layout.preferredWidth > appletItem.metrics.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredWidth > 0 )){ blockParabolicEffect = true; layoutWidth = applet.Layout.preferredWidth; } else{ layoutWidth = appletItem.metrics.iconSize; } } else{ layoutWidth = appletItem.metrics.iconSize; } } if (wrapper.zoomScale === 1) { if (blockParabolicEffect) { disableScaleWidth = true; } else { disableScaleWidth = false; } } } Item{ id:_wrapperContainer width:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal){ return wrapper.width; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutWidth; } else { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { var wrapperContainerThickness = parent.zoomScaleWidth * (appletItem.metrics.totals.thickness); return appletItem.screenEdgeMarginSupported ? wrapperContainerThickness + appletItem.metrics.margin.screenEdge : wrapperContainerThickness; } else { return parent.zoomScaleWidth * wrapper.layoutWidth; } } } height:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isVertical){ return wrapper.height; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutHeight; } else { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { var wrapperContainerThickness = parent.zoomScaleHeight * (appletItem.metrics.totals.thickness); return appletItem.screenEdgeMarginSupported ? wrapperContainerThickness + appletItem.metrics.margin.screenEdge : wrapperContainerThickness; } else { return parent.zoomScaleHeight * wrapper.layoutHeight; } } } opacity: appletShadow.active ? 0 : 1 readonly property int appliedEdgeMargin: { if (appletItem.isInternalViewSplitter) { return appletItem.metrics.margin.screenEdge + appletItem.metrics.margin.thickness; } return appletItem.screenEdgeMarginSupported ? 0 : appletItem.metrics.margin.screenEdge; } ///Secret MouseArea to be used by the folder widget Loader{ anchors.fill: parent active: communicator.overlayLatteIconIsActive && applet.pluginName === "org.kde.plasma.folder" && !appletItem.acceptMouseEvents sourceComponent: MouseArea{ onClicked: latteView.extendedInterface.toggleAppletExpanded(applet.id); } } Item{ id: _containerForOverlayIcon anchors.fill: parent } Loader{ id: _overlayIconLoader anchors.fill: parent active: communicator.overlayLatteIconIsActive property color backgroundColor: "black" property color glowColor: "white" sourceComponent: LatteCore.IconItem{ id: overlayIconItem anchors.fill: parent source: { if (communicator.appletIconItemIsShown()) return communicator.appletIconItem.source; else if (communicator.appletImageItemIsShown()) return communicator.appletImageItem.source; return ""; } providesColors: indicators.info.needsIconColors && source != "" usesPlasmaTheme: communicator.appletIconItemIsShown() ? communicator.appletIconItem.usesPlasmaTheme : false Binding{ target: _overlayIconLoader property: "backgroundColor" when: overlayIconItem.providesColors value: overlayIconItem.backgroundColor } Binding{ target: _overlayIconLoader property: "glowColor" when: overlayIconItem.providesColors value: overlayIconItem.glowColor } Loader{ anchors.centerIn: parent active: root.debugModeOverloadedIcons sourceComponent: Rectangle{ width: 30 height: 30 color: "green" opacity: 0.65 } } } } //! WrapperContainer States states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: _wrapperContainer.appliedEdgeMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target:_wrapperContainer; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: _wrapperContainer.appliedEdgeMargin; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: _wrapperContainer.appliedEdgeMargin; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: _wrapperContainer; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: _wrapperContainer; anchors.leftMargin: 0; anchors.rightMargin: _wrapperContainer.appliedEdgeMargin; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } Loader{ anchors.fill: _wrapperContainer active: appletItem.isInternalViewSplitter && root.inConfigureAppletsMode sourceComponent: Item { anchors.fill: parent PlasmaCore.SvgItem{ id:splitterImage anchors.centerIn: parent width: Math.min(root.maxJustifySplitterSize, appletItem.metrics.iconSize) height: width rotation: root.isVertical ? 90 : 0 svg: PlasmaCore.Svg{ imagePath: root.universalSettings.splitterIconPath() } layer.enabled: graphicsSystem.isAccelerated layer.effect: DropShadow { radius: root.appShadowSize fast: true samples: 2 * radius color: root.appShadowColor verticalOffset: 2 } } } } ///Shadow in applets Loader{ id: appletShadow anchors.fill: appletItem.appletWrapper active: appletItem.applet && graphicsSystem.isAccelerated && !appletColorizer.mustBeShown && (root.enableShadows && applet.pluginName !== root.plasmoidName) onActiveChanged: { if (active && !isSeparator && graphicsSystem.isAccelerated) { wrapperContainer.opacity = 0; } else { wrapperContainer.opacity = 1; } } opacity: isSeparator ? 0.4 : 1 sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor //"#ff080808" fast: true samples: 2 * radius source: communicator.overlayLatteIconIsActive ? _wrapperContainer : appletItem.applet radius: shadowSize verticalOffset: root.forceTransparentPanel || root.forcePanelForBusyBackground ? 0 : 2 property int shadowSize : root.appShadowSize } } BrightnessContrast{ id:hoveredImage anchors.fill: _wrapperContainer source: _wrapperContainer enabled: appletItem.isSquare && !originalAppletBehavior && !indicators.info.providesHoveredAnimation && opacity != 0 ? true : false opacity: appletMouseArea.containsMouse ? 1 : 0 brightness: 0.25 contrast: 0.15 visible: !indicators.info.providesHoveredAnimation Behavior on opacity { NumberAnimation { duration: appletItem.animations.speedFactor.current*appletItem.animations.duration.large } } } BrightnessContrast { id: _clickedEffect anchors.fill: _wrapperContainer source: _wrapperContainer visible: clickedAnimation.running && !indicators.info.providesClickedAnimation } /* onHeightChanged: { if ((index == 1)|| (index==3)){ console.log("H: "+index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } } onZoomScaleChanged:{ if ((index == 1)|| (index==3)){ console.log(index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } }*/ Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" //! red visualizer, in debug mode for the applets that use fillWidth or fillHeight //! green, for the rest border.color: (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal) ? "red" : "green" border.width: 1 } } Behavior on zoomScale { id: animatedScaleBehavior enabled: !appletItem.parabolic.directRenderingEnabled || restoreAnimation.running NumberAnimation { duration: 3 * appletItem.animationTime easing.type: Easing.OutCubic } } Behavior on zoomScale { enabled: !animatedScaleBehavior.enabled NumberAnimation { duration: 0 } } function calculateScales( currentMousePosition ){ if (parabolic.factor.zoom===1) { return; } //use the new parabolic effect manager in order to handle all parabolic effect messages var scales = parabolic.applyParabolicEffect(index, currentMousePosition, center); //Left hiddenSpacer if(appletItem.firstAppletInContainer){ hiddenSpacerLeft.nScale = scales.leftScale - 1; } //Right hiddenSpacer ///there is one more item in the currentLayout ???? if(appletItem.lastAppletInContainer){ hiddenSpacerRight.nScale = scales.rightScale - 1; } zoomScale = parabolic.factor.zoom; } //scale function signalUpdateScale(nIndex, nScale, step){ if(appletItem && !appletItem.containsMouse && (appletItem.index === nIndex)){ if ( ((canBeHovered && !appletItem.originalAppletBehavior) || appletItem.latteApplet) && (applet && applet.status !== PlasmaCore.Types.HiddenStatus) ){ if(!appletItem.latteApplet){ if(nScale >= 0) zoomScale = nScale + step; else zoomScale = zoomScale + step; } } } } function sltUpdateLowerItemScale(delegateIndex, newScale, step) { if (delegateIndex === appletItem.index) { if (communicator.parabolicEffectIsSupported) { communicator.bridge.parabolic.client.hostRequestUpdateLowerItemScale(newScale, step); return; } if (!appletItem.isSeparator && !appletItem.isHidden) { //! when accepted signalUpdateScale(delegateIndex, newScale, step); if (newScale > 1) { // clear lower items parabolic.sglUpdateLowerItemScale(delegateIndex-1, 1, 0); } } else { parabolic.sglUpdateLowerItemScale(delegateIndex-1, newScale, step); } } else if ((newScale === 1) && (appletItem.index < delegateIndex)) { //! apply zoom clearing if (communicator.parabolicEffectIsSupported) { communicator.bridge.parabolic.client.hostRequestUpdateLowerItemScale(1, step); } else { signalUpdateScale(appletItem.index, 1, 0); } } } function sltUpdateHigherItemScale(delegateIndex, newScale, step) { if (delegateIndex === appletItem.index) { if (communicator.parabolicEffectIsSupported) { communicator.bridge.parabolic.client.hostRequestUpdateHigherItemScale(newScale, step); return; } if (!appletItem.isSeparator && !appletItem.isHidden) { //! when accepted signalUpdateScale(delegateIndex, newScale, step); if (newScale > 1) { // clear higher items parabolic.sglUpdateHigherItemScale(delegateIndex+1, 1, 0); } } else { parabolic.sglUpdateHigherItemScale(delegateIndex+1, newScale, step); } } else if ((newScale === 1) && (appletItem.index > delegateIndex)) { //! apply zoom clearing if (communicator.parabolicEffectIsSupported) { communicator.bridge.parabolic.client.hostRequestUpdateHigherItemScale(1, step); } else { signalUpdateScale(appletItem.index, 1, 0); } } } Component.onCompleted: { parabolic.sglUpdateLowerItemScale.connect(sltUpdateLowerItemScale); parabolic.sglUpdateHigherItemScale.connect(sltUpdateHigherItemScale); } Component.onDestruction: { parabolic.sglUpdateLowerItemScale.disconnect(sltUpdateLowerItemScale); parabolic.sglUpdateHigherItemScale.disconnect(sltUpdateHigherItemScale); } }// Main task area // id:wrapper diff --git a/containment/package/contents/ui/debug/DebugWindow.qml b/containment/package/contents/ui/debug/DebugWindow.qml index 5e75f9e9..f8106ffb 100644 --- a/containment/package/contents/ui/debug/DebugWindow.qml +++ b/containment/package/contents/ui/debug/DebugWindow.qml @@ -1,849 +1,849 @@ /* * 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.extras 2.0 as PlasmaExtras import org.kde.latte.core 0.2 as LatteCore Window{ width: mainGrid.width + 10 height: Math.min(mainGrid.height+10, Screen.height - visibilityManager.thicknessNormalOriginal) visible: true title: "#debugwindow#" property string space:" : " PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent verticalScrollBarPolicy: Qt.ScrollBarAsNeeded horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff flickableItem.flickableDirection: Flickable.VerticalFlick Grid{ id:mainGrid columns: 2 Text{ text: "Screen id"+space } Text{ text: latteView && latteView.positioner ? latteView.positioner.currentScreenName : "___" } Text{ text: "Screen Geometry"+space } Text{ text: { if (latteView && latteView.screenGeometry){ return latteView.screenGeometry.x+","+latteView.screenGeometry.y+ " "+latteView.screenGeometry.width+"x"+latteView.screenGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Window Geometry"+space } Text{ text: { if (latteView) { return latteView.x + "," + latteView.y + " "+latteView.width+ "x"+latteView.height; } else { return "_,_ _x_"; } } } Text{ text: "On Primary"+space } Text{ text: { if (latteView && latteView.onPrimary) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Contents Width"+space } Text{ text: layoutsContainer.contentsWidth } Text{ text: "Contents Height"+space } Text{ text: layoutsContainer.contentsHeight } Text{ text: "Max Length"+space } Text{ text: root.maxLengthPerCentage +"%" } Text{ text: "Max Length (pixels)"+space } Text{ text: root.maxLength } Text{ text: "Min Length"+space } Text{ text: root.minLengthPerCentage +"%" } Text{ text: "Min Length (pixels)"+space } Text{ text: root.minLength } Text{ text: "Offset (pixels)"+space } Text{ text: root.offset } Text{ text: "Mask"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.mask) { return latteView.effects.mask.x +", "+ latteView.effects.mask.y+" "+latteView.effects.mask.width+"x"+latteView.effects.mask.height; } else { return "_,_ _x_"; } } } Text{ text: "Absolute Geometry"+space } Text{ text: { if (latteView && latteView.absoluteGeometry) { return latteView.absoluteGeometry.x + ", " + latteView.absoluteGeometry.y + " " + latteView.absoluteGeometry.width + "x" + latteView.absoluteGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Local Geometry"+space } Text{ text: { if (latteView && latteView.localGeometry) { return latteView.localGeometry.x + ", " + latteView.localGeometry.y + " " + latteView.localGeometry.width + "x" + latteView.localGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Draw Effects"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.drawEffects) return "Yes"; else return "No"; } } Text{ text: "Effects Area"+space } Text{ text: { if (latteView && latteView.effects && latteView.effects.rect) { return latteView.effects.rect.x + ", " + latteView.effects.rect.y + " " +latteView.effects.rect.width + "x" + latteView.effects.rect.height; } else { return "_,_ _x_"; } } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Is Hidden (flag)"+space } Text{ text: { if (latteView && latteView.visibility && latteView.visibility.isHidden) return "Yes"; else return "No"; } } Text{ text: "Contains Mouse (flag)"+space } Text{ text: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) return "Yes"; else return "No"; } } Text{ text: "Edit Mode"+space } Text{ text: { if (root.editMode) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Location"+space } Text{ text: { switch(plasmoid.location){ case PlasmaCore.Types.LeftEdge: return "Left Edge"; break; case PlasmaCore.Types.RightEdge: return "Right Edge"; break; case PlasmaCore.Types.TopEdge: return "Top Edge"; break; case PlasmaCore.Types.BottomEdge: return "Bottom Edge"; break; } return " : " + plasmoid.location; } } Text{ text: "Alignment"+space } Text{ text: { switch(plasmoid.configuration.alignment){ case LatteCore.Types.Left: return "Left"; break; case LatteCore.Types.Right: return "Right"; break; case LatteCore.Types.Center: return "Center"; break; case LatteCore.Types.Top: return "Top"; break; case LatteCore.Types.Bottom: return "Bottom"; break; case LatteCore.Types.Justify: return "Justify"; break; } return " : " + plasmoid.configuration.alignment; } } Text{ text: "Visibility"+space } Text{ text: { if (!latteView || !latteView.visibility) return ""; switch(latteView.visibility.mode){ case LatteCore.Types.AlwaysVisible: return "Always Visible"; break; case LatteCore.Types.AutoHide: return "Auto Hide"; break; case LatteCore.Types.DodgeActive: return "Dodge Active"; break; case LatteCore.Types.DodgeMaximized: return "Dodge Maximized"; break; case LatteCore.Types.DodgeAllWindows: return "Dodge All Windows"; break; case LatteCore.Types.DodgeAllWindows: return "Dodge All Windows"; break; case LatteCore.Types.WindowsGoBelow: return "Windows Go Below"; break; case LatteCore.Types.WindowsCanCover: return "Windows Can Cover"; break; case LatteCore.Types.WindowsAlwaysCover: return "Windows Always Cover"; break; case LatteCore.Types.SideBar: return "OnDemand SideBar"; break; case LatteCore.Types.NormalWindow: return "Normal Window"; break; case LatteCore.Types.None: return "None"; break; } return " : " + latteView.visibility.mode; } } Text{ text: "Zoom Factor"+space } Text{ text: parabolic.factor.zoom } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Icon Size (current)"+space } Text{ text: metrics.iconSize } Text{ text: "Icon Size (user)"+space } Text{ text: plasmoid.configuration.iconSize } Text{ text: "Icon Size (portion)"+space } Text{ text: metrics.portionIconSize } Text{ text: "Icon Size (auto decrease), Enabled"+space } Text{ text: { if (autosize.isActive) return "Yes"; else return "No"; } } Text{ text: "Icon Size (auto decrease)"+space } Text{ text: autosize.iconSize } Text{ text: "Length Padding (pixels)"+space } Text{ text: metrics.padding.length } Text{ text: "Length Margin (pixels)"+space } Text{ text: metrics.margin.length } Text{ text: "Thickness Margin"+space } Text{ text: metrics.margin.thickness } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Show Panel Background (user)"+space } Text{ text: { if (plasmoid.configuration.useThemePanel) return "Yes"; else return "No"; } } Text{ text: "Force Transparent Panel (auto)"+space } Text{ text: { if (root.forceTransparentPanel) return "Yes"; else return "No"; } } Text{ text: "Background Length"+space } Text{ text: background.totals.visualLength } Text{ text: "Background Thickness(user)"+space } Text{ text: plasmoid.configuration.panelSize + "%" } Text{ text: "Background Thickness(auto)"+space } Text{ text: background.totals.visualThickness } Text{ text: "Background Transparency"+space } Text{ text: root.panelTransparency + "%" } Text{ text: "Background Shadows Active"+space } Text{ text: { if (root.panelShadowsActive) return "Yes"; else return "No"; } } Text{ text: "Background Shadow"+space } Text{ text: background.shadows.headThickness } Text{ text: "Background Head Thickness Padding"+space } Text{ text: background.paddings.headThickness } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Mask - Normal Thickness"+space } Text{ text: visibilityManager.thicknessNormal } Text{ text: "Thickness Uses Panel Size"+space } Text{ text: visibilityManager.panelIsBiggerFromIconSize } Text{ text: "Behave As Plasma Panel"+space } Text{ text: { if (root.behaveAsPlasmaPanel) return "Yes"; else return "No"; } } Text{ text: "Draw Shadows (external)"+space } Text{ text: { if (root.drawShadowsExternal) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applet Hovered"+space } Text{ text: "--"//layoutsContainer.hoveredIndex } Text{ text: "Task Hovered"+space } Text{ text: "--"//root.latteAppletHoveredIndex } Text{ text: "In Normal State"+space } Text{ text: visibilityManager.normalState } Text{ text: "Animations Both Axis"+space } Text{ text: animations.needBothAxis.count } Text{ text: "Animations Only Length"+space } Text{ text: animations.needLength.count } Text{ text: "Animations Need Thickness"+space } Text{ text: animations.needThickness.count } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Start Layout Shown Applets"+space } Text{ - text: layoutsContainer.startLayout.shownApplets + text: layouter.startLayout.shownApplets } Text{ text: "Start Layout Applets (with fill)"+space } Text{ - text: layoutsContainer.startLayout.fillApplets + text: layouter.startLayout.fillApplets } Text{ text: "Start Layout Size (no fill applets)"+space } Text{ - text: layoutsContainer.startLayout.sizeWithNoFillApplets+" px." + text: layouter.startLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Main Layout Shown Applets"+space } Text{ - text: layoutsContainer.mainLayout.shownApplets + text: layouter.mainLayout.shownApplets } Text{ text: "Main Layout Applets (with fill)"+space } Text{ - text: layoutsContainer.mainLayout.fillApplets + text: layouter.mainLayout.fillApplets } Text{ text: "Main Layout Size (no fill applets)"+space } Text{ - text: layoutsContainer.mainLayout.sizeWithNoFillApplets+" px." + text: layouter.mainLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "End Layout Shown Applets"+space } Text{ text: layoutsContainer.endLayout.shownApplets } Text{ text: "End Layout Applets (with fill)"+space } Text{ - text: layoutsContainer.endLayout.fillApplets + text: layouter.endLayout.fillApplets } Text{ text: "End Layout Size (no fill applets)"+space } Text{ - text: layoutsContainer.endLayout.sizeWithNoFillApplets+" px." + text: layouter.endLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applets Max Inner ZoomFactor" + space } Text{ text: layoutsContainer.applets.require.maxInnerZoomFactor } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applets need Windows Tracking"+space } Text{ text: layoutsContainer.applets.require.windowsTrackingCount } Text{ text: "Last Active Window Current Screen (id)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.lastActiveWindow.isValid ? latteView.windowsTracker.currentScreen.lastActiveWindow.winId : "--" } Text{ text: "Last Active Window Current Screen (title)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.lastActiveWindow.isValid ? latteView.windowsTracker.currentScreen.lastActiveWindow.display : "--" elide: Text.ElideRight } Text{ text: "Last Active Window All Screens (id)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.allScreens.lastActiveWindow.isValid ? latteView.windowsTracker.allScreens.lastActiveWindow.winId : "--" } Text{ text: "Last Active Window All Screens (title)"+space } Text{ text: latteView && latteView.windowsTracker && latteView.windowsTracker.allScreens.lastActiveWindow.isValid ? latteView.windowsTracker.allScreens.lastActiveWindow.display : "--" elide: Text.ElideRight } } } } diff --git a/containment/package/contents/ui/debug/Tag.qml b/containment/package/contents/ui/debug/Tag.qml index d3bdd3f3..084112ed 100644 --- a/containment/package/contents/ui/debug/Tag.qml +++ b/containment/package/contents/ui/debug/Tag.qml @@ -1,44 +1,43 @@ /* * Copyright 2020 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.0 Item { id: tag - width: _label.width + 4 height: _label.height + 4 readonly property alias background: _background readonly property alias label: _label Rectangle { id: _background anchors.fill: parent color: "black" } Text { id: _label anchors.centerIn: parent text: " --- " color: "white" font.pointSize: 11 } } diff --git a/containment/package/contents/ui/editmode/ConfigOverlay.qml b/containment/package/contents/ui/editmode/ConfigOverlay.qml index 3dd8ecd8..241cd2b4 100644 --- a/containment/package/contents/ui/editmode/ConfigOverlay.qml +++ b/containment/package/contents/ui/editmode/ConfigOverlay.qml @@ -1,556 +1,556 @@ /* * 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.7 import QtQuick.Layouts 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 MouseArea { id: configurationArea z: 1000 width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.width : thickness height: plasmoid.formFactor === PlasmaCore.Types.Vertical ? root.height : thickness visible: root.inConfigureAppletsMode hoverEnabled: root.inConfigureAppletsMode focus: true cursorShape: { if (currentApplet && tooltip.visible && currentApplet.latteStyleApplet) { return root.isHorizontal ? Qt.SizeHorCursor : Qt.SizeVerCursor; } return Qt.ArrowCursor; } property bool isResizingLeft: false property bool isResizingRight: false property Item currentApplet property Item previousCurrentApplet property int lastX property int lastY property int appletX property int appletY readonly property int thickness: visibilityManager.thicknessNormalOriginalValue - visibilityManager.extraNormalThickMask - 1 readonly property int spacerHandleSize: units.smallSpacing onHeightChanged: tooltip.visible = false; onWidthChanged: tooltip.visible = false; function hoveredItem(x, y) { //! main layout var relevantLayout = mapFromItem(layoutsContainer.mainLayout,0,0); var item = layoutsContainer.mainLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); if (!item) { // start layout relevantLayout = mapFromItem(layoutsContainer.startLayout,0,0); item = layoutsContainer.startLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); } if (!item) { relevantLayout = mapFromItem(layoutsContainer.endLayout,0,0); item = layoutsContainer.endLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); } return item; } function relevantLayoutForApplet(curapplet) { var relevantLayout; if (curapplet.parent === layoutsContainer.mainLayout) { relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0); } else if (curapplet.parent === layoutsContainer.startLayout) { relevantLayout = mapFromItem(layoutsContainer.startLayout, 0, 0); } else if (curapplet.parent === layoutsContainer.endLayout) { relevantLayout = mapFromItem(layoutsContainer.endLayout, 0, 0); } return relevantLayout; } onPositionChanged: { if (pressed) { var padding = units.gridUnit * 3; if (currentApplet && (mouse.x < -padding || mouse.y < -padding || mouse.x > width + padding || mouse.y > height + padding)) { var newCont = plasmoid.containmentAt(mouse.x, mouse.y); if (newCont && newCont != plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, mouse.x, mouse.y); newCont.addApplet(currentApplet.applet, newPos.x, newPos.y); root.dragOverlay.currentApplet = null; return; } } if(currentApplet){ if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.y += (mouse.y - lastY); // handle.y = currentApplet.y; } else { currentApplet.x += (mouse.x - lastX); // handle.x = currentApplet.x; } } lastX = mouse.x; lastY = mouse.y; var item = hoveredItem(mouse.x, mouse.y); if (item && item !== placeHolder) { placeHolder.parent = configurationArea; var posInItem = mapToItem(item, mouse.x, mouse.y); if ((plasmoid.formFactor === PlasmaCore.Types.Vertical && posInItem.y < item.height/2) || (plasmoid.formFactor !== PlasmaCore.Types.Vertical && posInItem.x < item.width/2)) { root.layoutManagerInsertBefore(item, placeHolder); } else { root.layoutManagerInsertAfter(item, placeHolder); } } } else { var item = hoveredItem(mouse.x, mouse.y); if (root.dragOverlay && item && item !== lastSpacer) { root.dragOverlay.currentApplet = item; } else { currentApplet = null; root.dragOverlay.currentApplet = null; } } if (root.dragOverlay.currentApplet) { hideTimer.stop(); tooltip.visible = true; tooltip.raise(); } } onExited: hideTimer.restart(); onCurrentAppletChanged: { previousCurrentApplet = currentApplet; if (!currentApplet || !root.dragOverlay.currentApplet) { hideTimer.restart(); return; } var relevantLayout = relevantLayoutForApplet(currentApplet) ; if (!relevantLayout) { return; } handle.x = relevantLayout.x + currentApplet.x; handle.y = relevantLayout.y + currentApplet.y; handle.width = currentApplet.width; handle.height = currentApplet.height; lockButton.checked = currentApplet.lockZoom; colorizingButton.checked = !currentApplet.userBlocksColorizing; repositionHandler.restart(); } onPressed: { if (!root.dragOverlay.currentApplet) { return; } var relevantApplet = mapFromItem(currentApplet, 0, 0); var rootArea = mapFromItem(root, 0, 0); appletX = mouse.x - relevantApplet.x + rootArea.x; appletY = mouse.y - relevantApplet.y + rootArea.y; lastX = mouse.x; lastY = mouse.y; placeHolder.width = currentApplet.width; placeHolder.height = currentApplet.height; handle.width = currentApplet.width; handle.height = currentApplet.height; root.layoutManagerInsertBefore(currentApplet, placeHolder); currentApplet.parent = root; currentApplet.x = lastX-appletX; currentApplet.y = lastY-appletY; currentApplet.z = 900; } onReleased: { if (!root.dragOverlay.currentApplet) { return; } if(currentApplet && currentApplet.applet){ if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.applet.configuration.length = handle.height; } else { currentApplet.applet.configuration.length = handle.width; } } configurationArea.isResizingLeft = false; configurationArea.isResizingRight = false; root.layoutManagerInsertBefore(placeHolder, currentApplet); placeHolder.parent = configurationArea; currentApplet.z = 1; var relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0); handle.x = relevantLayout.x + currentApplet.x; handle.y = relevantLayout.y + currentApplet.y; // handle.width = currentApplet.width; // handle.height = currentApplet.height; root.layoutManagerSave(); root.layoutManagerMoveAppletsBasedOnJustifyAlignment(); - layoutsContainer.updateSizeForAppletsInFill(); + layouter.updateSizeForAppletsInFill(); } onWheel: { if (!currentApplet || !currentApplet.latteStyleApplet) { return; } var angle = wheel.angleDelta.y / 8; if (angle > 12) currentApplet.latteStyleApplet.increaseLength(); else if (angle < 12) currentApplet.latteStyleApplet.decreaseLength(); } Item { id: placeHolder visible: configurationArea.containsMouse Layout.fillWidth: currentApplet ? currentApplet.Layout.fillWidth : false Layout.fillHeight: currentApplet ? currentApplet.Layout.fillHeight : false } //Because of the animations for the applets the handler can not catch up to //reposition itself when the currentApplet position or size changes. //This timer fixes that situation Timer { id: repositionHandler interval: 100 onTriggered: handle.updatePlacement(); } Timer { id: hideTimer interval: animations.duration.large * 2 onTriggered: { if (!tooltipMouseArea.containsMouse) { tooltip.visible = false; currentApplet = null; } } } Connections { target: currentApplet onXChanged: handle.updatePlacement(); onYChanged: handle.updatePlacement(); onWidthChanged: handle.updatePlacement(); onHeightChanged: handle.updatePlacement() } Item { id: handle visible: currentApplet && (configurationArea.containsMouse || tooltipMouseArea.containsMouse) //BEGIN functions function updatePlacement(){ if(currentApplet){ var transformChoords = configurationArea.mapFromItem(currentApplet, 0, 0) handle.x = transformChoords.x; handle.y = transformChoords.y; handle.width = currentApplet.width; handle.height = currentApplet.height; repositionHandler.restart(); } } //END functions Item { id: handleVisualItem width: root.isHorizontal ? parent.width : thickness height: root.isHorizontal ? thickness : parent.height readonly property int thickness: root.isHorizontal ? parent.height - metrics.margin.screenEdge : parent.width - metrics.margin.screenEdge Rectangle{ anchors.fill: parent color: theme.backgroundColor radius: 3 opacity: 0.5 } PlasmaCore.IconItem { source: "transform-move" width: Math.min(parent.width, parent.height) height: width anchors.centerIn: parent opacity: 0.5 } states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } Behavior on opacity { NumberAnimation { duration: animations.duration.large easing.type: Easing.InOutQuad } } } PlasmaCore.Dialog { id: tooltip visualParent: currentApplet type: PlasmaCore.Dialog.Dock flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.BypassWindowManagerHint | Qt.ToolTip location: plasmoid.location onVisualParentChanged: { if (visualParent && currentApplet && (currentApplet.applet || currentApplet.isSeparator || currentApplet.isInternalViewSplitter)) { configureButton.visible = !currentApplet.isInternalViewSplitter && (currentApplet.applet.pluginName !== root.plasmoidName) && currentApplet.applet.action("configure") && currentApplet.applet.action("configure").enabled; closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled; lockButton.visible = !currentApplet.isInternalViewSplitter && (currentApplet.applet.pluginName !== root.plasmoidName) && !currentApplet.isSeparator; colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter; label.text = currentApplet.isInternalViewSplitter ? i18n("Justify Splitter") : currentApplet.applet.title; } } mainItem: MouseArea { id: tooltipMouseArea enabled: currentApplet width: handleRow.childrenRect.width + (2 * handleRow.spacing) height: Math.max(configureButton.height, label.contentHeight, closeButton.height) hoverEnabled: true LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true onEntered: hideTimer.stop(); onExited: hideTimer.restart(); Row { id: handleRow anchors.horizontalCenter: parent.horizontalCenter spacing: 2*units.smallSpacing Row{ spacing: units.smallSpacing PlasmaComponents.ToolButton { id: configureButton anchors.verticalCenter: parent.verticalCenter iconSource: "configure" tooltip: i18n("Configure applet") onClicked: { tooltip.visible = false; currentApplet.applet.action("configure").trigger(); } } PlasmaComponents.Label { id: label anchors.verticalCenter: parent.verticalCenter anchors.rightMargin: units.smallSpacing textFormat: Text.PlainText maximumLineCount: 1 } Row{ spacing: units.smallSpacing/2 PlasmaComponents.ToolButton{ id: colorizingButton checkable: true iconSource: "color-picker" tooltip: i18n("Enable painting for this applet") onCheckedChanged: { currentApplet.userBlocksColorizing = !checked; root.layoutManagerSaveOptions(); } } PlasmaComponents.ToolButton{ id: lockButton checkable: true iconSource: checked ? "lock" : "unlock" tooltip: i18n("Disable parabolic effect for this applet") onCheckedChanged: { currentApplet.lockZoom = checked; root.layoutManagerSaveOptions(); } } PlasmaComponents.ToolButton { id: closeButton anchors.verticalCenter: parent.verticalCenter iconSource: "delete" tooltip: i18n("Remove applet") onClicked: { tooltip.visible = false; if(currentApplet && currentApplet.applet) currentApplet.applet.action("remove").trigger(); } } } } } } } states: [ State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: configurationArea anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } } ] } diff --git a/containment/package/contents/ui/layouts/AppletsContainer.qml b/containment/package/contents/ui/layouts/AppletsContainer.qml index 2d169755..2c50ad6b 100644 --- a/containment/package/contents/ui/layouts/AppletsContainer.qml +++ b/containment/package/contents/ui/layouts/AppletsContainer.qml @@ -1,348 +1,222 @@ /* * Copyright 2019 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.7 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import "./abilities" as Abilities Abilities.AbilityGrid { id: appletsContainer columns: root.isVertical ? 1 : 0 columnSpacing: 0 flow: isHorizontal ? Grid.LeftToRight : Grid.TopToBottom rows: root.isHorizontal ? 1 : 0 rowSpacing: 0 //Layout.preferredWidth: width //Layout.preferredHeight: height property int alignment: LatteCore.Types.BottomEdgeCenterAlign property int beginIndex: 0 property int offset: 0 - readonly property int count: children.length - - //it is used in calculations for fillWidth,fillHeight applets - property int shownApplets: 0 - property int fillApplets: 0 - - //it is used in calculations for fillWidth,fillHeight applets - property int sizeWithNoFillApplets: 0 - - readonly property int maxIndex: 99999 - property int firstVisibleIndex: -1 - property int lastVisibleIndex: -1 - - //! do not update during dragging/moving applets inConfigureAppletsMode - readonly property bool updateIsBlocked: (root.dragOverlay && root.dragOverlay.pressed) - || animations.appletsInParentChange - - Binding{ - target: appletsContainer - property:"sizeWithNoFillApplets" - when: appletsContainer && !updateIsBlocked && animations.inNormalFillCalculationsState - value: { - var space = 0; - for (var i=0; i=0 - && indexer.hidden.indexOf(appletItem.index)<0 - && indexer.separators.indexOf(appletItem.index)<0 - && appletItem.index < ind) { - ind = appletItem.index; - } - } - - return ind === maxIndex ? -1 : ind; - } - } - - Binding{ - target: appletsContainer - property:"lastVisibleIndex" - when: appletsContainer && !updateIsBlocked - value: { - var ind = -1; - for(var i=0; i=0 - && indexer.hidden.indexOf(appletItem.index)<0 - && indexer.separators.indexOf(appletItem.index)<0 - && appletItem.index > ind) { - ind = appletItem.index; - } - } - - return ind; - } - } - - onCountChanged: { - if (root.editMode) { - //! this is mainly used when removing/adding internal view splitters - //! in order to not break the parabolic effect from wrong indexes - root.updateIndexes(); - } - } - - onFillAppletsChanged: layoutsContainer.updateSizeForAppletsInFill(); - onShownAppletsChanged: layoutsContainer.updateSizeForAppletsInFill(); - onSizeWithNoFillAppletsChanged: layoutsContainer.updateSizeForAppletsInFill(); - - //////////////////////////BEGIN states //user set Panel Positions // 0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom states: [ ///Left Edge State { name: "leftCenter" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: appletsContainer.offset; } }, State { name: "leftTop" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeTopAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.offset; anchors.bottomMargin:appletsContainer.lastMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "leftBottom" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeBottomAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.lastMargin; anchors.bottomMargin:appletsContainer.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Right Edge State { name: "rightCenter" when: appletsContainer.alignment === LatteCore.Types.RightEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: appletsContainer.offset; } }, State { name: "rightTop" when: appletsContainer.alignment === LatteCore.Types.RightEdgeTopAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.offset; anchors.bottomMargin:appletsContainer.lastMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "rightBottom" when: appletsContainer.alignment === LatteCore.Types.RightEdgeBottomAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.lastMargin; anchors.bottomMargin:appletsContainer.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Bottom Edge State { name: "bottomCenter" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: appletsContainer.offset; anchors.verticalCenterOffset: 0; } }, State { name: "bottomLeft" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeLeftAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: appletsContainer.offset; anchors.rightMargin:appletsContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "bottomRight" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeRightAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: appletsContainer.lastMargin; anchors.rightMargin:appletsContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Top Edge State { name: "topCenter" when: appletsContainer.alignment === LatteCore.Types.TopEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: appletsContainer.offset; anchors.verticalCenterOffset: 0; } }, State { name: "topLeft" when: appletsContainer.alignment === LatteCore.Types.TopEdgeLeftAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: appletsContainer.offset; anchors.rightMargin:appletsContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "topRight" when: appletsContainer.alignment === LatteCore.Types.TopEdgeRightAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: appletsContainer.lastMargin; anchors.rightMargin:appletsContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] ////////////////END states } diff --git a/containment/package/contents/ui/layouts/LayoutsContainer.qml b/containment/package/contents/ui/layouts/LayoutsContainer.qml index 4cc6f63d..91cb96fd 100644 --- a/containment/package/contents/ui/layouts/LayoutsContainer.qml +++ b/containment/package/contents/ui/layouts/LayoutsContainer.qml @@ -1,432 +1,404 @@ /* * 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.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment import "./abilities" as AbilitiesTypes import "../debug" as Debug -import "../../code/HeuristicTools.js" as HeuristicTools Item{ id: layoutsContainer readonly property bool isHidden: root.inStartup || (latteView && latteView.visibility && latteView.visibility.isHidden) readonly property bool useMaxLength: plasmoid.configuration.alignment === LatteCore.Types.Justify - /* && ((!root.inConfigureAppletsMode && !root.behaveAsPlasmaPanel ) - || (behaveAsPlasmaPanel && root.inConfigureAppletsMode))*/ - property int allCount: root.latteApplet ? _mainLayout.count-1+latteApplet.tasksCount : _mainLayout.count property int currentSpot: -1000 - readonly property int fillApplets: _startLayout.fillApplets + _mainLayout.fillApplets + _endLayout.fillApplets - readonly property alias startLayout : _startLayout readonly property alias mainLayout: _mainLayout readonly property alias endLayout: _endLayout readonly property AbilitiesTypes.AbilityLayouts applets: AbilitiesTypes.AbilityLayouts{ startLayout: _startLayout mainLayout: _mainLayout endLayout: _endLayout } + signal contentsLengthChanged(); + Binding { target: layoutsContainer property: "x" when: !visibilityManager.inLocationAnimation value: { if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isHorizontal && useMaxLength ){ return ((latteView.width/2) - (root.maxLength/2) + background.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isVertical){ return; } if (layoutsContainer.isHidden && root.isVertical) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } Binding{ target: layoutsContainer property: "y" when: !visibilityManager.inLocationAnimation value: { if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isVertical && useMaxLength ) { return ((latteView.height/2) - (root.maxLength/2) + background.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isHorizontal){ return; } if (layoutsContainer.isHidden && root.isHorizontal) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } width: root.isHorizontal && useMaxLength ? root.maxLength : parent.width height: root.isVertical && useMaxLength ? root.maxLength : parent.height z:10 property bool animationSent: false property bool shouldCheckHalfs: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (_mainLayout.children>1) property int contentsWidth: _startLayout.width + _mainLayout.width + _endLayout.width property int contentsHeight: _startLayout.height + _mainLayout.height + _endLayout.height onContentsWidthChanged: { if (root.isHorizontal){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); } if (latteView && ((contentsWidth >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.addEvent(layoutsContainer); } - layoutsContainer.updateSizeForAppletsInFill(); + contentsLengthChanged(); delayUpdateMaskArea.start(); } } onContentsHeightChanged: { if (root.isVertical){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); } if (latteView && ((contentsHeight >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.removeEvent(layoutsContainer); } - layoutsContainer.updateSizeForAppletsInFill(); + contentsLengthChanged(); delayUpdateMaskArea.start(); } } onXChanged: root.updateEffectsArea(); onYChanged: root.updateEffectsArea(); EnvironmentActions { active: root.scrollAction !== LatteContainment.Types.ScrollNone || root.dragActiveWindowEnabled || root.closeActiveWindowEnabled alignment: _mainLayout.alignment } AppletsContainer { id: _startLayout beginIndex: 0 offset: background.totals.shadowsLength/2 //it is applied only in Justify when both background length shadows are drawn alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeLeftAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeLeftAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeTopAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeTopAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } AppletsContainer { id: _mainLayout z:10 //be on top of start and end layouts beginIndex: 100 offset: { if (background.hasBothLengthShadows && !centered) { //! it is used for Top/Bottom/Left/Right alignments when they show both background length shadows return background.offset + background.totals.shadowsLength/2; } return (root.panelAlignment === LatteCore.Types.Justify) ? 0 : background.offset } readonly property bool centered: (root.panelAlignment === LatteCore.Types.Center) || (root.panelAlignment === LatteCore.Types.Justify) readonly property bool reversed: Qt.application.layoutDirection === Qt.RightToLeft alignment: { if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (centered) return LatteCore.Types.LeftEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.LeftEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.LeftEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (centered) return LatteCore.Types.RightEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.RightEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.RightEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { if (centered) return LatteCore.Types.BottomEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.BottomEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.BottomEdgeRightAlign; } } if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (centered) return LatteCore.Types.TopEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.TopEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.TopEdgeRightAlign; } } return LatteCore.Types.BottomEdgeCenterAlign; } transitions: Transition { enabled: editModeVisual.plasmaEditMode AnchorAnimation { duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } } AppletsContainer { id: _endLayout beginIndex: 200 offset: background.totals.shadowsLength/2 //it is applied only in Justify when both background length shadows are drawn alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeRightAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeRightAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeBottomAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeBottomAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } - function updateSizeForAppletsInFill() { - if (!updateSizeForAppletsInFillTimer.running) { - HeuristicTools.updateSizeForAppletsInFill(); - updateSizeForAppletsInFillTimer.start(); - } - } - Connections { target: metrics onIconSizeAnimationEnded: delayUpdateMaskArea.start(); } - Connections { - target: animations - onInNormalFillCalculationsStateChanged: { - if (animations.inNormalFillCalculationsState) { - layoutsContainer.updateSizeForAppletsInFill(); - } - } - } - //! Debug Elements Loader{ - anchors.top: debugLayout.top - anchors.horizontalCenter: debugLayout.horizontalCenter + anchors.top: startLayout.top + anchors.horizontalCenter: startLayout.horizontalCenter active: root.debugModeLayouter - readonly property Item debugLayout: _startLayout + readonly property Item debugLayout: layouter.startLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 - readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height + readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { - return "no_show:" + debugLayout.shownApplets + " / no_fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; + return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ - anchors.top: debugLayout.top - anchors.horizontalCenter: debugLayout.horizontalCenter + anchors.top: endLayout.top + anchors.horizontalCenter: endLayout.horizontalCenter active: root.debugModeLayouter - readonly property Item debugLayout: _endLayout + readonly property Item debugLayout: layouter.endLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 - readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height + readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { - return "no_show:" + debugLayout.shownApplets + " / no_fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; + return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ - anchors.top: debugLayout.top - anchors.horizontalCenter: debugLayout.horizontalCenter + anchors.top: mainLayout.top + anchors.horizontalCenter: mainLayout.horizontalCenter active: root.debugModeLayouter z:70 - readonly property Item debugLayout: _mainLayout + readonly property Item debugLayout: layouter.mainLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 - readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height + readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { - return "no_show:" + debugLayout.shownApplets + " / no_fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; + return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ - anchors.top: _mainLayout.top + anchors.top: mainLayout.top anchors.left: parent.left active: root.debugModeLayouter readonly property Item debugLayout: layoutsContainer sourceComponent: Debug.Tag{ background.color: "blue" label.text: tagText label.color: "yellow" label.font.pointSize: 13 label.font.bold: true readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height readonly property int layoutsLength: { if (root.isVertical) { - return _startLayout.height + _mainLayout.height + _endLayout.height; + return layouter.startLayout.grid.height + layouter.mainLayout.grid.height + layouter.endLayout.grid.height; } - return _startLayout.width + _mainLayout.width + _endLayout.width; + return layouter.startLayout.grid.width + layouter.mainLayout.grid.width + layouter.endLayout.grid.width; } readonly property string tagText: { return "MAX:" + root.maxLength + " / TOT:"+layoutLength + " / LAYS:"+ layoutsLength; } } } - //! This timer is needed in order to reduce the calls to heavy cpu function - //! HeuristicTools.updateSizeForAppletsInFill() - Timer{ - id: updateSizeForAppletsInFillTimer - interval: 50 - onTriggered: HeuristicTools.updateSizeForAppletsInFill(); - } - //! This timer is needed in order to update mask area after ContentsWidth/Height and iconSize changes Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { animations.needLength.removeEvent(layoutsContainer); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("LayoutsContainer timer: delayUpdateMaskArea called..."); } } } } diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index c67810b3..b8a6e360 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1653 +1,1659 @@ /* * 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.8 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.components 1.0 as LatteComponents import org.kde.latte.private.app 0.1 as LatteApp import org.kde.latte.private.containment 0.1 as LatteContainment import "abilities" as Ability import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "./background" as Background import "./debug" as Debug import "../code/LayoutManager.js" as LayoutManager Item { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeLayouter: Qt.application.arguments.indexOf("--layouter")>=0 property bool debugModeLocalGeometry: Qt.application.arguments.indexOf("--localgeometry")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 readonly property int version: LatteCore.Environment.makeVersion(0,9,4) property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!LatteCore.WindowSystem.compositingActive) { //! In NOCOMPOSITING mode VIEWS should behave as real windows and that way //! we gain also the snapping features from KWin return true; } if (!latteView || !latteView.visibility) { return false; } if (screenEdgeMarginEnabled && plasmoid.configuration.fittsLawIsRequested) { //! dont use when floating views are requesting Fitt's Law return false; } var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); return (visibilityManager.panelIsBiggerFromIconSize && (parabolic.factor.maxZoom === 1.0) && (plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && !root.editMode && !visibilityManager.inLocationAnimation); } readonly property bool behaveAsDockWithMask: !behaveAsPlasmaPanel property int viewType: { var staticLayout = (plasmoid.configuration.minLength === plasmoid.configuration.maxLength); if ((plasmoid.configuration.alignment === LatteCore.Types.Justify || staticLayout) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (parabolic.factor.maxZoom === 1.0)) { return LatteCore.Types.PanelView; } return LatteCore.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) readonly property bool ignoreRegularFilesDragging: !root.editMode && (dragInfo.computationsAreValid || foreDropArea.dragInfo.computationsAreValid) && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers readonly property Item dragInfo: Item { property bool entered: backDropArea.dragInfo.entered || foreDropArea.dragInfo.entered property bool isTask: backDropArea.dragInfo.isTask || foreDropArea.dragInfo.isTask property bool isPlasmoid: backDropArea.dragInfo.isPlasmoid || foreDropArea.dragInfo.isPlasmoid property bool isSeparator: backDropArea.dragInfo.isSeparator || foreDropArea.dragInfo.isSeparator property bool isLatteTasks: backDropArea.dragInfo.isLatteTasks || foreDropArea.dragInfo.isLatteTasks property bool onlyLaunchers: backDropArea.dragInfo.onlyLaunchers || foreDropArea.dragInfo.onlyLaunchers // onIsPlasmoidChanged: console.log("isPlasmoid :: " + backDropArea.dragInfo.isPlasmoid + " _ " + foreDropArea.dragInfo.isPlasmoid ); // onEnteredChanged: console.log("entered :: " + backDropArea.dragInfo.entered + " _ " + foreDropArea.dragInfo.entered ); } property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && LatteCore.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.currentScreen.activeWindowTouching || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && latteView.windowsTracker.currentScreen.existsWindowTouching) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || solidBusyForTouchingBusyVerticalView || plasmaStyleBusyForTouchingBusyVerticalView || !LatteCore.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && LatteCore.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !latteView.windowsTracker.currentScreen.existsWindowTouching && !(windowColors === LatteContainment.Types.ActiveWindowColors && selectedWindowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && (root.themeColors === LatteContainment.Types.SmartThemeColors) && ( (root.forceTransparentPanel && colorizerManager.backgroundIsBusy) || normalBusyForTouchingBusyVerticalView ) property bool normalBusyForTouchingBusyVerticalView: (latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers isBusy transparency*/ && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized /*&& !plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups*/) property bool solidBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case /*(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmoid.configuration.solidBackgroundForMaximized && !plasmaBackgroundForPopups)*/ property bool plasmaStyleBusyForTouchingBusyVerticalView: false //DISABLED, until to check if the normalBusyForTouchingBusyVerticalView is enough to catch and handle the case //(latteView && latteView.windowsTracker /*is touching a vertical view that is in busy state and the user prefers solidness*/ /* && latteView.windowsTracker.currentScreen.isTouchingBusyVerticalView && root.themeColors === LatteContainment.Types.SmartThemeColors && plasmoid.configuration.backgroundOnlyOnMaximized && plasmaBackgroundForPopups)*/ property bool hideThickScreenGap: screenEdgeMarginEnabled && plasmoid.configuration.hideScreenGapForMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.existsWindowMaximized property bool hideLengthScreenGaps: hideThickScreenGap && (latteView.visibility.mode === LatteCore.Types.AlwaysVisible || latteView.visibility.mode === LatteCore.Types.WindowsGoBelow) && (plasmoid.configuration.alignment === LatteCore.Types.Justify) && plasmoid.configuration.maxLength>85 && !root.editMode property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== LatteContainment.Types.PlasmaThemeColors || windowColors !== LatteContainment.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: latteView && latteView.extendedInterface.hasExpandedApplet; readonly property bool hasUserSpecifiedBackground: (latteView && latteView.layout && latteView.layout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !LatteCore.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: parabolic.factor.zoom>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool closeActiveWindowEnabled: plasmoid.configuration.closeActiveWindowEnabled property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (maxLengthPerCentage===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: LatteCore.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !LatteCore.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property bool plasma515: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,15,0) property bool plasma518: LatteCore.Environment.plasmaDesktopVersion >= LatteCore.Environment.makeVersion(5,18,0) readonly property int minAppletLengthInConfigure: 64 readonly property int maxJustifySplitterSize: 96 property int latteAppletPos: -1 property real minLengthPerCentage: plasmoid.configuration.minLength property real maxLengthPerCentage: hideLengthScreenGaps ? 100 : plasmoid.configuration.maxLength property int minLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? width : width * (minLengthPerCentage/100) } else { return behaveAsPlasmaPanel && LatteCore.WindowSystem.compositingActive ? height : height * (minLengthPerCentage/100) } } property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (maxLengthPerCentage/100) } else { return behaveAsPlasmaPanel ? height : height * (maxLengthPerCentage/100) } } property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(background.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } var forcedNoShadows = (plasmoid.configuration.panelShadows && disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.currentScreen.activeWindowMaximized); if (forcedNoShadows) { return false; } var transparencyCheck = (blurEnabled || (!blurEnabled && background.currentOpacity>20)); //! Draw shadows for isBusy state only when current panelTransparency is greater than 10% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && transparencyCheck) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !forcedNoShadows) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*metrics.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*metrics.maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === LatteContainment.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === LatteContainment.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int offset: { if (behaveAsPlasmaPanel) { return 0; } if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } property int editShadow: { if (!LatteCore.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property bool screenEdgeMarginEnabled: plasmoid.configuration.screenEdgeMargin >= 0 && !plasmoid.configuration.shrinkThickMargins property int widthMargins: root.isVertical ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int heightMargins: root.isHorizontal ? metrics.totals.thicknessEdges : metrics.totals.lengthEdges property int panelAlignment: plasmoid.configuration.alignment readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property alias animations: _animations readonly property alias background: _background readonly property alias autosize: _autosize readonly property alias indexer: _indexer readonly property alias indicatorsManager: indicators + readonly property alias layouter: _layouter readonly property alias metrics: _metrics readonly property alias parabolic: _parabolic readonly property alias parabolicManager: _parabolicManager readonly property alias maskManager: visibilityManager readonly property alias layoutsContainerItem: layoutsContainer readonly property alias latteView: _interfaces.view readonly property alias layoutsManager: _interfaces.layoutsManager readonly property alias shortcutsEngine: _interfaces.globalShortcuts readonly property alias themeExtended: _interfaces.themeExtended readonly property alias universalSettings: _interfaces.universalSettings readonly property QtObject viewLayout: latteView && latteView.layout ? latteView.layout : null readonly property QtObject selectedWindowsTracker: { if (latteView && latteView.windowsTracker) { switch(plasmoid.configuration.activeWindowFilter) { case LatteContainment.Types.ActiveInCurrentScreen: return latteView.windowsTracker.currentScreen; case LatteContainment.Types.ActiveFromAllScreens: return latteView.windowsTracker.allScreens; } } return null; } // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool badges3DStyle: universalSettings ? universalSettings.badges3DStyle : true property bool enableShadows: plasmoid.configuration.appletShadowsEnabled property bool dockIsHidden: latteView ? latteView.visibility.isHidden : true property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: true property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === metrics.iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on offset { enabled: editModeVisual.editAnimationInFullThickness NumberAnimation { id: offsetAnimation duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onEditModeChanged: { if (!editMode) { - layoutsContainer.updateSizeForAppletsInFill(); + layouter.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelAlignmentChanged: { if (!root.editMode) { return; } if (root.editMode/*!inConfigureAppletsMode*/){ if (panelAlignment===LatteCore.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } LayoutManager.save(); updateIndexes(); } onLatteViewChanged: { if (latteView) { latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onMaxLengthChanged: { - layoutsContainer.updateSizeForAppletsInFill(); + layouter.updateSizeForAppletsInFill(); } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.alignment === LatteCore.Types.Left) plasmoid.configuration.alignment = LatteCore.Types.Top; else if (plasmoid.configuration.alignment === LatteCore.Types.Right) plasmoid.configuration.alignment = LatteCore.Types.Bottom; } else { if (plasmoid.configuration.alignment === LatteCore.Types.Top) plasmoid.configuration.alignment = LatteCore.Types.Left; else if (plasmoid.configuration.alignment === LatteCore.Types.Bottom) plasmoid.configuration.alignment = LatteCore.Types.Right; } } Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; LayoutManager.metrics = metrics; upgrader_v010_alignment(); LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); - animations.appletsInParentChange = true; + layouter.appletsInParentChange = true; if (latteView) { latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.alignment === LatteCore.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && root.inConfigureAppletsMode) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, pos); } else { - LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, Math.floor(layoutsContainer.mainLayout.count / 2)); + LayoutManager.insertAtIndex(layoutsContainer.mainLayout, container, Math.floor(layouter.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function layoutManager() { return LayoutManager; } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotPreviewsShown(){ if (latteView) { latteView.extendedInterface.deactivateApplets(); } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } - function updateSizeForAppletsInFill() { - layoutsContainer.updateSizeForAppletsInFill(); - } - function layoutManagerMoveAppletsBasedOnJustifyAlignment() { if (plasmoid.configuration.alignment !== 10) { return; } - animations.appletsInParentChange = true; + layouter.appletsInParentChange = true; var splitter = -1; var startChildrenLength = layoutsContainer.startLayout.children.length; //! Check if there is a splitter inside start layout after the user was dragging its applets for (var i=0; i=0) { for (var i=startChildrenLength-1; i>=splitter; --i){ var item = layoutsContainer.startLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.mainLayout, item, 0); } } var splitter2 = -1; var endChildrenLength = layoutsContainer.endLayout.children.length; //! Check if there is a splitter inside endlayout after the user was dragging its applets for (var i=0; i=0) { for (var i=0; i<=splitter2; ++i){ var item = layoutsContainer.endLayout.children[0]; item.parent = layoutsContainer.mainLayout; } } //! Validate applets positioning and move applets out of splitters to start/endlayouts accordingly splitMainLayoutToLayouts(); - animations.appletsInParentChange = false; + layouter.appletsInParentChange = false; } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { - animations.appletsInParentChange = true; + layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); if (splitter > 0) { for (var i=0; i 0) { splitter2 = splitter2 - splitter; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=totalChildren-1; i>=splitter2+1; --i){ var item = layoutsContainer.mainLayout.children[i]; LayoutManager.insertAtIndex(layoutsContainer.endLayout, item, 0); } } - animations.appletsInParentChange = false; + layouter.appletsInParentChange = false; } } function joinLayoutsToMainLayout() { - animations.appletsInParentChange = true; + layouter.appletsInParentChange = true; console.log("LAYOUTS: Moving applets from THREE to MAIN Layout mode..."); var totalChildren1 = layoutsContainer.mainLayout.children.length; for (var i=totalChildren1-1; i>=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } - animations.appletsInParentChange = false; + layouter.appletsInParentChange = false; } function upgrader_v010_alignment() { //! IMPORTANT, special case because it needs to be loaded on Component constructor if (!plasmoid.configuration.alignmentUpgraded) { plasmoid.configuration.alignment = plasmoid.configuration.panelPosition; plasmoid.configuration.alignmentUpgraded = true; } } //END functions ////BEGIN interfaces Connections { target: LatteCore.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { parabolic.sglClearZoom.connect(titleTooltipDialog.hide); } Component.onDestruction: { parabolic.sglClearZoom.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{ animations: _animations indexer: _indexer + layouter: _layouter metrics: _metrics parabolic: _parabolic } } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } Item { id: graphicsSystem readonly property bool isAccelerated: (GraphicsInfo.api !== GraphicsInfo.Software) && (GraphicsInfo.api !== GraphicsInfo.Unknown) } Upgrader { id: upgrader } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: Debug.DebugWindow{} } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.06 } } } VisibilityManager{ id: visibilityManager applets: layoutsContainer.applets } DragDropArea { id: backDropArea anchors.fill: parent readonly property bool higherPriority: latteView && latteView.containsDrag && ((root.dragInfo.isPlasmoid && root.dragInfo.isSeparator) || (foreDropArea.dragInfo.computationsAreValid && !root.dragInfo.isPlasmoid && !root.dragInfo.onlyLaunchers)) Item{ anchors.fill: layoutsContainer Background.MultiLayered{ id: _background } } Layouts.LayoutsContainer { id: layoutsContainer } DragDropArea { id: foreDropArea anchors.fill: parent visible: !backDropArea.higherPriority isForeground: true /* Rectangle { anchors.fill: parent color: "blue" opacity: 0.5 }*/ } } Colorizer.Manager { id: colorizerManager } Item { id: dndSpacer width: root.isHorizontal ? length : thickness height: root.isHorizontal ? thickness : length readonly property int length: metrics.totals.length readonly property int thickness: metrics.totals.thickness + metrics.margin.screenEdge Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:1500 LatteComponents.AddItem{ id: dndSpacerAddItem width: root.isHorizontal ? parent.width : parent.width - metrics.margin.screenEdge height: root.isHorizontal ? parent.height - metrics.margin.screenEdge: parent.height states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: dndSpacerAddItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: dndSpacerAddItem; anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } } ///////////////END UI elements ///////////////BEGIN ABILITIES Ability.Animations { id: _animations metrics: _metrics settings: universalSettings } Ability.AutoSize { id: _autosize layouts: layoutsContainer + layouter: _layouter metrics: _metrics visibility: visibilityManager } Ability.Indexer { id: _indexer layouts: layoutsContainer } + Ability.Layouter { + id: _layouter + animations: _animations + indexer: _indexer + layouts: layoutsContainer + } + Ability.Metrics { id: _metrics animations: _animations autosize: _autosize background: _background indicators: indicatorsManager } Ability.ParabolicEffect { id: _parabolic animations: _animations applets: layoutsContainer.applets view: latteView } LatteApp.Interfaces { id: _interfaces plasmoidInterface: plasmoid Component.onCompleted: { view.interfacesGraphicObj = _interfaces; } onViewChanged: { if (view) { view.interfacesGraphicObj = _interfaces; } } } ///////////////END ABILITIES ///////////////BEGIN TIMER elements //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements Loader{ anchors.fill: parent active: root.debugModeLocalGeometry sourceComponent: Rectangle{ x: latteView.localGeometry.x y: latteView.localGeometry.y width: latteView.localGeometry.width height: latteView.localGeometry.height color: "blue" border.width: 2 border.color: "red" opacity: 0.35 } } }