diff --git a/containment/package/contents/ui/AutomaticItemSizer.qml b/containment/package/contents/ui/AutomaticItemSizer.qml new file mode 100644 index 000000000..c226e69be --- /dev/null +++ b/containment/package/contents/ui/AutomaticItemSizer.qml @@ -0,0 +1,234 @@ +/* +* 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 0.2 as Latte + +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: !root.containsOnlyPlasmaTasks && layoutsContainer.fillApplets<=0 + + property bool automaticSizeAnimation: false + + readonly property int automaticStep: 8 + readonly property int historyMaxSize: 10 + readonly property int historyMinSize: 4 + property int automaticIconSizeBasedSize: -1 //it is not set, this is the default + + //! Prediction History of the algorithm in order to track cases where the algorithm produces + //! grows and shrinks endlessly + property variant history: [] + + onAutomaticIconSizeBasedSizeChanged: { + if (!automaticSizeAnimation) { + automaticSizeAnimation = true; + root.slotAnimationsNeedBothAxis(1); + } + } + + onIsActiveChanged: clearHistory(); + + Connections { + target: root + + onContainsOnlyPlasmaTasksChanged: sizer.updateAutomaticIconSize(); + onEditModeChanged: sizer.updateAutomaticIconSize(); + onMaxLengthChanged: { + if (root.editMode) { + sizer.updateAutomaticIconSize(); + } + } + onProportionIconSizeChanged: { + if (root.proportionIconSize!==-1) { + sizer.updateAutomaticIconSize(); + } + } + + onIconSizeChanged: { + if (((root.iconSize === sizer.automaticIconSizeBasedSize) || (root.iconSize === root.maxIconSize)) && sizer.automaticSizeAnimation){ + root.slotAnimationsNeedBothAxis(-1); + sizer.automaticSizeAnimation=false; + } + } + } + + Connections { + target: latteView + onWidthChanged:{ + if (root.isHorizontal && root.proportionIconSize!==-1) { + sizer.updateAutomaticIconSize(); + } + } + + onHeightChanged:{ + if (root.isVertical && root.proportionIconSize!==-1) { + sizer.updateAutomaticIconSize(); + } + } + } + + //! 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 updateAutomaticIconSize() { + if ( !doubleCallAutomaticUpdateIconSize.running && !visibilityManager.inTempHiding + && ((visibilityManager.normalState || root.editMode) + && (sizer.isActive || (!sizer.isActive && root.iconSize!==root.maxIconSize))) + && (root.iconSize===root.maxIconSize || root.iconSize === sizer.automaticIconSizeBasedSize) ) { + + //!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.panelPosition === Latte.Types.Justify) ? + layoutsContainer.startLayout.height+layoutsContainer.mainLayout.height+layoutsContainer.endLayout.height : layoutsContainer.mainLayout.height + } else { + layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? + layoutsContainer.startLayout.width+layoutsContainer.mainLayout.width+layoutsContainer.endLayout.width : layoutsContainer.mainLayout.width + } + + var toShrinkLimit = maxLength-((1+(root.zoomFactor-1))*(root.iconSize + lengthMargins)); + var toGrowLimit = maxLength-((1+(root.zoomFactor-1))*(root.iconSize + lengthMargins)); + + //console.log("toShrinkLimit: "+ toShrinkLimit); + //console.log("toGrowLimit: "+ toGrowLimit); + + var newIconSizeFound = false; + if (layoutLength > toShrinkLimit) { //must shrink + // console.log("step3"); + var nextIconSize = root.maxIconSize; + + do { + nextIconSize = nextIconSize - automaticStep; + var factor = nextIconSize / root.iconSize; + var nextLength = factor * layoutLength; + + } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); + + var intLength = Math.round(layoutLength); + var intNextLength = Math.round(nextLength); + + automaticIconSizeBasedSize = nextIconSize; + newIconSizeFound = true; + + addPrediction(intLength, intNextLength); + // console.log("Step 3 - found:"+automaticIconSizeBasedSize); + } else if ((layoutLength 0 && !producesEndlessLoop(intLength2, intNextLength2)) { + if (foundGoodSize === root.maxIconSize) { + automaticIconSizeBasedSize = -1; + } else { + automaticIconSizeBasedSize = foundGoodSize; + } + newIconSizeFound = true + + addPrediction(intLength2, intNextLength2); + // console.log("Step 4 - found:"+automaticIconSizeBasedSize); + } else { + // console.log("Step 4 - did not found..."); + } + } + } + } + + //! This functions makes sure to call the updateAutomaticIconSize(); 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.updateAutomaticIconSize(); + } + } + } +} diff --git a/containment/package/contents/ui/DebugWindow.qml b/containment/package/contents/ui/DebugWindow.qml index 30988ada3..30fc5c181 100644 --- a/containment/package/contents/ui/DebugWindow.qml +++ b/containment/package/contents/ui/DebugWindow.qml @@ -418,7 +418,7 @@ Window{ } Text{ - text: root.automaticIconSizeBasedSize + text: automaticItemSizer.automaticIconSizeBasedSize } Text{ diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index 98f681d1d..84b8bf540 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -109,7 +109,7 @@ Item{ value: root.behaveAsPlasmaPanel && !root.editMode ? thicknessAsPanel : thicknessZoomOriginal } - property bool validIconSize: (root.iconSize===root.maxIconSize || root.iconSize === root.automaticIconSizeBasedSize) + property bool validIconSize: (root.iconSize===root.maxIconSize || root.iconSize === automaticItemSizer.automaticIconSizeBasedSize) property bool inPublishingState: validIconSize && !inSlidingIn && !inSlidingOut && !inTempHiding && !inForceHiding Binding{ @@ -313,7 +313,7 @@ Item{ onNormalStateChanged: { if (normalState) { - root.updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); root.updateSizeForAppletsInFill(); } } @@ -598,7 +598,7 @@ Item{ } } - var validIconSize = (root.iconSize===root.maxIconSize || root.iconSize === root.automaticIconSizeBasedSize); + var validIconSize = (root.iconSize===root.maxIconSize || root.iconSize === automaticItemSizer.automaticIconSizeBasedSize); //console.log("reached updating geometry ::: "+dock.maskArea); if(inPublishingState && (normalState || root.editMode)) { @@ -759,11 +759,11 @@ Item{ if (manager.inTempHiding) { manager.inTempHiding = false; - updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); } manager.inTempHiding = false; - updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); if (manager.debugMagager) { console.log("showing animation ended..."); diff --git a/containment/package/contents/ui/editmode/Visual.qml b/containment/package/contents/ui/editmode/Visual.qml index f9477c6cc..a071f1ded 100644 --- a/containment/package/contents/ui/editmode/Visual.qml +++ b/containment/package/contents/ui/editmode/Visual.qml @@ -380,7 +380,7 @@ Item{ editVisual.editAnimationEnded = true; editVisual.editAnimationInFullThickness = true; updateEffectsArea(); - updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); visibilityManager.updateMaskArea(); } } diff --git a/containment/package/contents/ui/layouts/LayoutsContainer.qml b/containment/package/contents/ui/layouts/LayoutsContainer.qml index 5fe5eb656..39bc66856 100644 --- a/containment/package/contents/ui/layouts/LayoutsContainer.qml +++ b/containment/package/contents/ui/layouts/LayoutsContainer.qml @@ -123,7 +123,7 @@ Item{ } if (latteView && ((contentsWidth >= root.maxLength) || firstHalfExited || secondHalfExited)) { - updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); } if (!animationSent) { @@ -148,7 +148,7 @@ Item{ } if (latteView && ((contentsHeight >= root.maxLength) || firstHalfExited || secondHalfExited)) { - updateAutomaticIconSize(); + automaticItemSizer.updateAutomaticIconSize(); } if (!animationSent) { diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index b5eba7618..5a5b4997b 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -73,9 +73,6 @@ Item { property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager - // 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 - property bool autoDecreaseIconSize: !containsOnlyPlasmaTasks && layoutsContainer.fillApplets<=0 property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!latteView || !latteView.visibility) { @@ -238,12 +235,10 @@ Item { property int appletsNeedWindowsTracking: 0 - property int automaticIconSizeBasedSize: -1 //it is not set, this is the defautl - //what is the highest icon size based on what icon size is used, screen calculated or user specified property int maxIconSize: proportionIconSize!==-1 ? proportionIconSize : plasmoid.configuration.iconSize - property int iconSize: automaticIconSizeBasedSize > 0 && autoDecreaseIconSize ? - Math.min(automaticIconSizeBasedSize, root.maxIconSize) : + property int iconSize: automaticItemSizer.automaticIconSizeBasedSize > 0 && automaticItemSizer.isActive ? + Math.min(automaticItemSizer.automaticIconSizeBasedSize, root.maxIconSize) : root.maxIconSize property int proportionIconSize: { //icon size based on screen height @@ -253,7 +248,6 @@ Item { return Math.max(16,Math.round(latteView.screenGeometry.height * plasmoid.configuration.proportionIconSize/100/8)*8); } - property int iconStep: 8 property int latteAppletPos: -1 property int maxLength: { if (root.isHorizontal) { @@ -334,8 +328,6 @@ Item { property string appShadowColorSolid: "#" + appChosenShadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox - //FIXME: this is not needed any more probably - property int previousAllTasks: -1 //is used to forbid updateAutomaticIconSize when hovering property int offset: { if (behaveAsPlasmaPanel) { return 0; @@ -644,15 +636,11 @@ Item { //// END OF Behaviors //////////////START OF CONNECTIONS - onContainsOnlyPlasmaTasksChanged: updateAutomaticIconSize(); - onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); - updateAutomaticIconSize(); clearZoom(); } else { - updateAutomaticIconSize(); layoutsContainer.updateSizeForAppletsInFill(); } @@ -732,9 +720,6 @@ Item { onMaxLengthChanged: { layoutsContainer.updateSizeForAppletsInFill(); - if (root.editMode) { - updateAutomaticIconSize(); - } } onToolBoxChanged: { @@ -743,21 +728,6 @@ Item { } } - property bool automaticSizeAnimation: false; - onAutomaticIconSizeBasedSizeChanged: { - if (!automaticSizeAnimation) { - automaticSizeAnimation = true; - slotAnimationsNeedBothAxis(1); - } - } - - onIconSizeChanged: { - if (((iconSize === automaticIconSizeBasedSize) || (iconSize === root.maxIconSize)) && automaticSizeAnimation){ - slotAnimationsNeedBothAxis(-1); - automaticSizeAnimation=false; - } - } - onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); @@ -778,11 +748,6 @@ Item { } } - onProportionIconSizeChanged: { - if (proportionIconSize!==-1) - updateAutomaticIconSize(); - } - // onIconSizeChanged: console.log("Icon Size Changed:"+iconSize); Component.onCompleted: { @@ -1376,85 +1341,6 @@ Item { } } - function updateAutomaticIconSize() { - if ( !doubleCallAutomaticUpdateIconSize.running && !visibilityManager.inTempHiding - && ((visibilityManager.normalState || root.editMode) - && (root.autoDecreaseIconSize || (!root.autoDecreaseIconSize && root.iconSize!=root.maxIconSize))) - && (iconSize===root.maxIconSize || iconSize === automaticIconSizeBasedSize) ) { - - //!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.panelPosition === Latte.Types.Justify) ? - layoutsContainer.startLayout.height+layoutsContainer.mainLayout.height+layoutsContainer.endLayout.height : layoutsContainer.mainLayout.height - } else { - layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? - layoutsContainer.startLayout.width+layoutsContainer.mainLayout.width+layoutsContainer.endLayout.width : layoutsContainer.mainLayout.width - } - - var toShrinkLimit = maxLength-((1+(root.zoomFactor-1))*(iconSize + lengthMargins)); - var toGrowLimit = maxLength-((1+(root.zoomFactor-1))*(iconSize + lengthMargins)); - - //console.log("toShrinkLimit: "+ toShrinkLimit); - //console.log("toGrowLimit: "+ toGrowLimit); - - var newIconSizeFound = false; - if (layoutLength > toShrinkLimit) { //must shrink - // console.log("step3"); - var nextIconSize = root.maxIconSize; - - do { - nextIconSize = nextIconSize - iconStep; - var factor = nextIconSize / iconSize; - var nextLength = factor * layoutLength; - - } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); - - automaticIconSizeBasedSize = nextIconSize; - newIconSizeFound = true; - // console.log("Step 3 - found:"+automaticIconSizeBasedSize); - } else if ((layoutLength 0) { - if (foundGoodSize === root.maxIconSize) { - automaticIconSizeBasedSize = -1; - } else { - automaticIconSizeBasedSize = foundGoodSize; - } - newIconSizeFound = true - // console.log("Step 4 - found:"+automaticIconSizeBasedSize); - } else { - // console.log("Step 4 - did not found..."); - } - } - } - } - function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); @@ -1537,15 +1423,6 @@ Item { Connections { target: latteView - onWidthChanged:{ - if (root.isHorizontal && proportionIconSize!==-1) - updateAutomaticIconSize(); - } - - onHeightChanged:{ - if (root.isVertical && proportionIconSize!==-1) - updateAutomaticIconSize(); - } onContextMenuIsShownChanged: { if (!latteView.contextMenuIsShown) { @@ -1797,6 +1674,10 @@ Item { } } + AutomaticItemSizer { + id: automaticItemSizer + } + VisibilityManager{ id: visibilityManager } DragDropArea { @@ -1915,21 +1796,6 @@ Item { } } - //! This functions makes sure to call the updateAutomaticIconSize(); 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; - root.updateAutomaticIconSize(); - } - } - } - //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer