Warning, /plasma/latte-dock/containment/package/contents/ui/abilities/privates/LayouterPrivate.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 import QtQuick 2.7 0007 import org.kde.plasma.plasmoid 2.0 0008 0009 import org.kde.latte.core 0.2 as LatteCore 0010 0011 import "./layouter" as LayouterElements 0012 0013 Item { 0014 property Item layouts: null 0015 property Item animations: null 0016 property Item indexer: null 0017 0018 readonly property int fillApplets: startLayout.fillApplets + mainLayout.fillApplets + endLayout.fillApplets 0019 readonly property int shownApplets: startLayout.shownApplets + mainLayout.shownApplets + endLayout.shownApplets 0020 readonly property int sizeWithNoFillApplets: startLayout.sizeWithNoFillApplets + mainLayout.sizeWithNoFillApplets + endLayout.sizeWithNoFillApplets 0021 0022 readonly property int maxLength: root.myView.alignment === LatteCore.Types.Justify ? contentsMaxLength : Math.min(root.minLength, contentsMaxLength) 0023 0024 readonly property int contentsMaxLength: root.maxLength - background.totals.paddingsLength 0025 0026 readonly property Item startLayout: LayouterElements.AppletsContainer { 0027 grid: layouts.startLayout 0028 } 0029 0030 readonly property Item mainLayout: LayouterElements.AppletsContainer { 0031 grid: layouts.mainLayout 0032 } 0033 0034 readonly property Item endLayout: LayouterElements.AppletsContainer { 0035 grid: layouts.endLayout 0036 } 0037 0038 onFillAppletsChanged: layouter.updateSizeForAppletsInFill(); 0039 onShownAppletsChanged: layouter.updateSizeForAppletsInFill(); 0040 onSizeWithNoFillAppletsChanged: layouter.updateSizeForAppletsInFill(); 0041 0042 //! FILLWIDTH/FILLHEIGHT COMPUTATIONS 0043 //! Computations in order to calculate correctly the sizes for applets 0044 //! that are requesting fillWidth or fillHeight 0045 0046 //! qBound style function that is specialized in Layouts 0047 //! meaning that -1 values are ignored for fillWidth(s)/Height(s) 0048 function appletPreferredLength(min, pref, max){ 0049 if (max === -1) { 0050 max = pref === -1 ? min : pref; 0051 } 0052 0053 if (pref === -1) { 0054 pref = max === -1 ? min : pref; 0055 } 0056 0057 return Math.min(Math.max(min,pref),max); 0058 } 0059 0060 0061 //! initialize AppletItems flag "inFillCalculations" in order 0062 //! to inform them that new calculations are taking place 0063 function initLayoutForFillsCalculations(layout) { 0064 for(var i=0; i<layout.children.length; ++i) { 0065 var curApplet = layout.children[i]; 0066 if (curApplet.isAutoFillApplet) { 0067 curApplet.inFillCalculations = true; 0068 } 0069 } 0070 } 0071 0072 //! during step1/pass1 all applets that provide valid metrics (minimum/preferred/maximum values) 0073 //! they gain a valid space in order to draw themeselves 0074 function computeStep1ForLayout(layout, availableSpace, sizePerApplet, noOfApplets, inMaxAutoFillCalculations) { 0075 for(var i=0; i<layout.children.length; ++i) { 0076 var curApplet = layout.children[i]; 0077 0078 // console.log( "org.kde.latte s3_-1 " + curApplet.pluginName + " : "+ curApplet.index +" (" +curApplet.isAutoFillApplet+","+!curApplet.isHidden +") "); 0079 // console.log( "org.kde.latte s3_-1 " + curApplet.pluginName + " : "+ availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets); 0080 0081 if (curApplet && curApplet.isAutoFillApplet && !curApplet.isHidden 0082 && (curApplet.applet || curApplet.isInternalViewSplitter)) { 0083 var minSize = curApplet.appletMinimumLength; 0084 var prefSize = curApplet.appletPreferredLength; 0085 var maxSize = curApplet.appletMaximumLength; 0086 0087 // console.log( "org.kde.latte s3_0 " + curApplet.pluginName + " : "+ curApplet.index +" (" +minSize+","+prefSize+","+maxSize+") "); 0088 0089 minSize = minSize>=0 && minSize!==Infinity ? minSize : -1; 0090 prefSize = minSize>=0 && prefSize!==Infinity ? prefSize : -1; 0091 0092 //! Qt ignores maximumlength=0 for applets that have set Layout.fillLength flag 0093 //! this was tracked through bug #445869, mediacontroller_plus applet case 0094 maxSize = maxSize>0 && maxSize!== Infinity ? maxSize : -1; 0095 0096 var appliedSize = -1; 0097 //! check if the applet does not provide any valid metrics and for that case 0098 //! the system must decide what space to be given after the applets that provide 0099 //! nice metrics are assigned their sizes 0100 //var systemDecide = ((minSize<0) && (prefSize<0) && (maxSize<0)); 0101 0102 var staticsize = (minSize>=0 && (maxSize === minSize) && (maxSize !== Infinity)); 0103 var systemDecide = (prefSize<0 && !staticsize); 0104 0105 if (!systemDecide) { 0106 if (noOfApplets>1) { 0107 appliedSize = appletPreferredLength(minSize, prefSize, maxSize); 0108 0109 // console.log( "org.kde.latte s3_1 " + curApplet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); 0110 } else if (noOfApplets===1) { 0111 //! at this step if only one applet has remained for which the max size is not null, 0112 //! then for this applet we make sure the maximum size does not exceed the available space 0113 //! in order for the applet to not be drawn outside the boundaries 0114 appliedSize = appletPreferredLength(minSize, prefSize, Math.min(maxSize, sizePerApplet)); 0115 0116 // console.log( "org.kde.latte s3_2 " + curApplet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") -> " + appliedSize); 0117 } 0118 0119 //! appliedSize is valid and is also lower than the availableSpace, if it is not lower then 0120 //! for this applet the needed space will be provided as a second pass in a fair way 0121 //! between all remained applets that did not gain a valid fill space 0122 if (appliedSize>=0 && appliedSize<=sizePerApplet) { 0123 var properSize = Math.min(appliedSize, availableSpace); 0124 var adjustedSize = curApplet.isHidden ? 0 : properSize; 0125 0126 if (inMaxAutoFillCalculations) { 0127 curApplet.maxAutoFillLength = adjustedSize; 0128 } else { 0129 curApplet.minAutoFillLength = adjustedSize; 0130 } 0131 0132 curApplet.inFillCalculations = false; 0133 availableSpace = Math.max(0, availableSpace - curApplet.maxAutoFillLength); 0134 noOfApplets = noOfApplets - 1; 0135 sizePerApplet = noOfApplets > 1 ? Math.floor(availableSpace / noOfApplets) : availableSpace; 0136 0137 // console.log( "org.kde.latte s3_3 " + curApplet.pluginName + " assigned: " + curApplet.maxAutoFillLength); 0138 } 0139 } 0140 0141 // console.log("org.kde.latte s3_r " +curApplet.pluginName + " : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets + "\n"); 0142 } 0143 } 0144 0145 return [availableSpace, sizePerApplet, noOfApplets]; 0146 } 0147 0148 //! during step2/pass2 all the applets with fills 0149 //! that remained with no computations from pass1 0150 //! are updated with the algorithm's proposed size 0151 function computeStep2ForLayout(layout, sizePerApplet, noOfApplets, inMaxAutoFillCalculations) { 0152 if (sizePerApplet>=0) { 0153 if (noOfApplets === 0) { 0154 //! when all applets have assigned some size and there is still free space, we must find 0155 //! the most demanding space applet and assign the remaining space to it 0156 0157 var mostDemandingAppletSize = 0; 0158 var mostDemandingApplet = undefined; 0159 0160 //! applets with no strong opinion 0161 var neutralAppletsNo = 0; 0162 var neutralApplets = []; 0163 0164 for(var i=0; i<layout.children.length; ++i) { 0165 var curApplet = layout.children[i]; 0166 0167 //! the most demanding applet is the one that has maximum size set to Infinity 0168 //! AND is not Neutral, meaning that it provided some valid metrics 0169 //! AND at the same time gained from step one the biggest space 0170 if (curApplet && curApplet.isAutoFillApplet && !curApplet.isHidden 0171 && (curApplet.applet || curApplet.isInternalViewSplitter)) { 0172 var minSize = curApplet.appletMinimumLength; 0173 var prefSize = curApplet.appletPreferredLength; 0174 var maxSize = curApplet.appletMaximumLength; 0175 0176 var isNeutral = (minSize<=0 && prefSize<=0); 0177 0178 // console.log( " org.kde.latte s4_0 " + curApplet.pluginName + " : (" +minSize+","+prefSize+","+maxSize+") "); 0179 0180 if (!isNeutral 0181 && ((inMaxAutoFillCalculations && curApplet.maxAutoFillLength>mostDemandingAppletSize) 0182 || (!inMaxAutoFillCalculations && curApplet.minAutoFillLength>mostDemandingAppletSize) )) { 0183 mostDemandingApplet = curApplet; 0184 mostDemandingAppletSize = inMaxAutoFillCalculations ? curApplet.maxAutoFillLength : curApplet.minAutoFillLength; 0185 } else if (isNeutral) { 0186 neutralAppletsNo = neutralAppletsNo + 1; 0187 neutralApplets.push(curApplet); 0188 } 0189 } 0190 } 0191 0192 if (mostDemandingApplet) { 0193 //! the most demanding applet gains all the remaining space 0194 0195 if (inMaxAutoFillCalculations) { 0196 mostDemandingApplet.maxAutoFillLength = mostDemandingApplet.maxAutoFillLength + sizePerApplet; 0197 } else { 0198 mostDemandingApplet.minAutoFillLength = mostDemandingApplet.minAutoFillLength + sizePerApplet; 0199 } 0200 0201 /*if (inMaxAutoFillCalculations) { 0202 console.log(" org.kde.latte s4_1 "+ mostDemandingApplet.applet.pluginName + " assigned max : " + mostDemandingApplet.maxAutoFillLength + "\n"); 0203 } else { 0204 console.log(" org.kde.latte s4_1 "+ mostDemandingApplet.applet.pluginName + " assigned min: " + mostDemandingApplet.minAutoFillLength + "\n"); 0205 }*/ 0206 } else if (neutralAppletsNo>0) { 0207 //! if no demanding applets was found then the available space is splitted equally 0208 //! between all neutralApplets 0209 var adjustedAppletSize = (sizePerApplet / neutralAppletsNo); 0210 for (var j=0; j<neutralApplets.length; ++j) { 0211 // console.log(" org.kde.latte s4_2.0 "+ neutralApplets[j].pluginName + " _ " + neutralApplets[j].maxAutoFillLength + " _ " + adjustedAppletSize); 0212 0213 if (inMaxAutoFillCalculations) { 0214 neutralApplets[j].maxAutoFillLength = neutralApplets[j].maxAutoFillLength + adjustedAppletSize; 0215 } else { 0216 neutralApplets[j].minAutoFillLength = neutralApplets[j].minAutoFillLength + adjustedAppletSize; 0217 } 0218 0219 // console.log(" org.kde.latte s4_2.1 "+ neutralApplets[j].pluginName + " assigned: " + sizePerApplet + "\n"); 0220 } 0221 } 0222 } else { 0223 for(var i=0; i<layout.children.length; ++i) { 0224 var curApplet = layout.children[i]; 0225 0226 if (curApplet && curApplet.isAutoFillApplet && !curApplet.isHidden && curApplet.inFillCalculations) { 0227 if (inMaxAutoFillCalculations) { 0228 curApplet.maxAutoFillLength = Math.max(curApplet.appletMinimumLength,sizePerApplet); 0229 } else { 0230 curApplet.minAutoFillLength = Math.max(curApplet.appletMinimumLength,sizePerApplet); 0231 } 0232 0233 // console.log(" org.kde.latte s4_3 "+ curApplet.pluginName + " assigned: " + sizePerApplet + "\n"); 0234 curApplet.inFillCalculations = false; 0235 } 0236 } 0237 } 0238 } 0239 } 0240 0241 //! initialize the three layouts and execute the step1/phase1 0242 //! it is used when the Centered (Main)Layout is used only or when the Main(Layout) 0243 //! is empty in Justify mode 0244 function initializationPhase(availableSpace, sizePerApplet, noOfApplets, inMaxAutoFillCalculations){ 0245 if (root.myView.alignment === LatteCore.Types.Justify) { 0246 initLayoutForFillsCalculations(startLayout.grid); 0247 initLayoutForFillsCalculations(endLayout.grid); 0248 } 0249 initLayoutForFillsCalculations(mainLayout.grid); 0250 0251 // console.log("s3..."); 0252 0253 //! first pass in order to update sizes for applet that want to fill space 0254 //! but their maximum metrics are lower than the sizePerApplet 0255 var res = computeStep1ForLayout(mainLayout.grid, availableSpace, sizePerApplet, noOfApplets, inMaxAutoFillCalculations); 0256 availableSpace = res[0]; sizePerApplet = res[1]; noOfApplets = res[2]; 0257 0258 // console.log( " i1 : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets ); 0259 0260 if (root.myView.alignment === LatteCore.Types.Justify) { 0261 res = computeStep1ForLayout(startLayout.grid, availableSpace, sizePerApplet, noOfApplets, inMaxAutoFillCalculations); 0262 availableSpace = res[0]; sizePerApplet = res[1]; noOfApplets = res[2]; 0263 // console.log( " i2 : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets ); 0264 0265 res = computeStep1ForLayout(endLayout.grid, availableSpace, sizePerApplet, noOfApplets, inMaxAutoFillCalculations); 0266 availableSpace = res[0]; sizePerApplet = res[1]; noOfApplets = res[2]; 0267 // console.log( " i3 : " + availableSpace + " _ " + sizePerApplet + " _ " + noOfApplets ); 0268 } 0269 0270 return [availableSpace, sizePerApplet, noOfApplets]; 0271 } 0272 0273 function updateFillAppletsWithTwoSteps(inMaxAutoFillCalculations) { 0274 var noA = startLayout.fillApplets + mainLayout.fillApplets + endLayout.fillApplets; 0275 var max_length = inMaxAutoFillCalculations ? contentsMaxLength : root.minLength 0276 0277 // console.log(" S3 _ SIZES ::: " + max_length + " ___ " + inMaxAutoFillCalculations + " __ " + startLayout.sizeWithNoFillApplets + " ___ " + mainLayout.sizeWithNoFillApplets + " ___ " + endLayout.sizeWithNoFillApplets); 0278 0279 //! compute the two free spaces around the centered layout 0280 //! they are called start and end accordingly 0281 var halfMainLayout = mainLayout.sizeWithNoFillApplets / 2; 0282 var availableSpaceStart = Math.max(0, max_length/2 - startLayout.sizeWithNoFillApplets - halfMainLayout /*- layoutsContainer.backgroundTailLength*/); 0283 var availableSpaceEnd = Math.max(0, max_length/2 - endLayout.sizeWithNoFillApplets - halfMainLayout /*- layoutsContainer.backgroundHeadLength*/); 0284 var availableSpace; 0285 0286 if (mainLayout.fillApplets === 0 || (startLayout.shownApplets ===0 && endLayout.shownApplets===0)){ 0287 //! no fill applets in main OR we are in alignment that all applets are in main 0288 availableSpace = availableSpaceStart + availableSpaceEnd - mainLayout.sizeWithNoFillApplets; 0289 } else { 0290 //! use the minimum available space in order to avoid overlaps 0291 availableSpace = 2 * Math.min(availableSpaceStart, availableSpaceEnd) - mainLayout.sizeWithNoFillApplets; 0292 } 0293 0294 var sizePerAppletMain = mainLayout.fillApplets > 0 ? availableSpace / noA : 0 ; 0295 0296 var noStart = startLayout.fillApplets; 0297 var noMain = mainLayout.fillApplets; 0298 var noEnd = endLayout.fillApplets; 0299 0300 //! initialize the computations 0301 initLayoutForFillsCalculations(startLayout.grid, inMaxAutoFillCalculations); 0302 initLayoutForFillsCalculations(mainLayout.grid, inMaxAutoFillCalculations); 0303 initLayoutForFillsCalculations(endLayout.grid, inMaxAutoFillCalculations); 0304 0305 var res; 0306 0307 // console.log(" org.kde.latte S3.1 main fill applets :: " + mainLayout.fillApplets); 0308 //! first pass 0309 if (mainLayout.fillApplets > 0){ 0310 res = computeStep1ForLayout(mainLayout.grid, availableSpace, sizePerAppletMain, noMain, inMaxAutoFillCalculations); 0311 sizePerAppletMain = res[1]; noMain = res[2]; 0312 var dif = (availableSpace - res[0]) / 2; 0313 availableSpaceStart = availableSpaceStart - dif; 0314 availableSpaceEnd = availableSpaceEnd - dif; 0315 } 0316 0317 var sizePerAppletStart = startLayout.fillApplets > 0 ? availableSpaceStart / noStart : 0 ; 0318 var sizePerAppletEnd = endLayout.fillApplets > 0 ? availableSpaceEnd / noEnd : 0 ; 0319 0320 if (startLayout.fillApplets > 0) { 0321 res = computeStep1ForLayout(startLayout.grid, availableSpaceStart, sizePerAppletStart, noStart, inMaxAutoFillCalculations); 0322 availableSpaceStart = res[0]; sizePerAppletStart = res[1]; noStart = res[2]; 0323 } 0324 if (endLayout.fillApplets > 0) { 0325 res = computeStep1ForLayout(endLayout.grid, availableSpaceEnd, sizePerAppletEnd, noEnd, inMaxAutoFillCalculations); 0326 availableSpaceEnd = res[0]; sizePerAppletEnd = res[1]; noEnd = res[2]; 0327 } 0328 0329 //// 0330 //! second pass 0331 0332 // console.log(" S ::: " +startLayout.fillApplets + " _ " + sizePerAppletStart + " _ " + noStart); 0333 0334 if (startLayout.fillApplets > 0) { 0335 if (mainLayout.fillApplets > 0) { 0336 //! finally adjust ALL startLayout fill applets size in mainlayouts final length 0337 noStart = startLayout.fillApplets; 0338 sizePerAppletStart = ((max_length/2) - (mainLayout.grid.length/2) - startLayout.sizeWithNoFillApplets) / noStart; 0339 } 0340 0341 computeStep2ForLayout(startLayout.grid, sizePerAppletStart, noStart, inMaxAutoFillCalculations); 0342 } 0343 0344 if (endLayout.fillApplets > 0) { 0345 if (mainLayout.fillApplets > 0) { 0346 //! finally adjust ALL endLayout fill applets size in mainlayouts final length 0347 noEnd = endLayout.fillApplets; 0348 sizePerAppletEnd = ((max_length/2) - (mainLayout.grid.length/2) - endLayout.sizeWithNoFillApplets) / noEnd; 0349 } 0350 0351 computeStep2ForLayout(endLayout.grid, sizePerAppletEnd, noEnd, inMaxAutoFillCalculations); 0352 } 0353 0354 if (mainLayout.fillApplets > 0) { 0355 var halfRemained = (max_length/2) - (mainLayout.grid.length/2); 0356 var freeSpaceAfterStart = halfRemained - startLayout.grid.length; 0357 var freeSpaceBeforeEnd = halfRemained - endLayout.grid.length; 0358 0359 if (freeSpaceAfterStart > 0 && freeSpaceBeforeEnd>0) { 0360 if (mainLayout.fillApplets > 0) { 0361 var minimumHalfAppletSizePossible = Math.min(freeSpaceAfterStart, freeSpaceBeforeEnd); 0362 sizePerAppletMain = Math.max(0, (minimumHalfAppletSizePossible * 2)/mainLayout.fillApplets); 0363 } 0364 0365 computeStep2ForLayout(mainLayout.grid, sizePerAppletMain, noMain, inMaxAutoFillCalculations); //default behavior 0366 } 0367 } 0368 } 0369 0370 function updateFillAppletsWithOneStep(inMaxAutoFillCalculations) { 0371 var max_length = inMaxAutoFillCalculations ? contentsMaxLength : root.minLength 0372 var noA = startLayout.fillApplets + mainLayout.fillApplets + endLayout.fillApplets; 0373 0374 // console.log(" org.kde.latte S2 _ SIZES ::: " + max_length + " ___ " + inMaxAutoFillCalculations + " __ " + startLayout.sizeWithNoFillApplets + " ___ " + mainLayout.sizeWithNoFillApplets + " ___ " + endLayout.sizeWithNoFillApplets); 0375 0376 var availableSpace = Math.max(0, max_length - startLayout.sizeWithNoFillApplets - mainLayout.sizeWithNoFillApplets - endLayout.sizeWithNoFillApplets); 0377 var sizePerApplet = availableSpace / noA; 0378 0379 var res = initializationPhase(availableSpace, sizePerApplet, noA, inMaxAutoFillCalculations); 0380 availableSpace = res[0]; sizePerApplet = res[1]; noA = res[2]; 0381 0382 // console.log("s4..."); 0383 0384 //! after step1 there is a chance that all applets were assigned a valid space 0385 //! but at the same time some space remained free. In such case we make sure 0386 //! that remained space will be assigned to the most demanding applet. 0387 //! This is achieved by <layout>No values. For step2 passing value!=0 0388 //! means default step2 behavior BUT value=0 means that remained space 0389 //! must be also assigned at the end. 0390 var remainedSpace = (noA === 0 && sizePerApplet > 0) ? true : false 0391 0392 var startNo = -1; 0393 var mainNo = -1; 0394 var endNo = -1; 0395 0396 if (remainedSpace) { 0397 if (startLayout.fillApplets > 0) { 0398 startNo = 0; 0399 } else if (endLayout.fillApplets > 0) { 0400 endNo = 0; 0401 } else if (mainLayout.fillApplets > 0) { 0402 mainNo = 0; 0403 } 0404 } 0405 0406 //! second pass in order to update sizes for applet that want to fill space 0407 //! these applets get the direct division of the available free space that 0408 //! remained from step1 OR the the free available space that no applet requested yet 0409 0410 computeStep2ForLayout(startLayout.grid, sizePerApplet, startNo, inMaxAutoFillCalculations); //default behavior 0411 computeStep2ForLayout(mainLayout.grid, sizePerApplet, mainNo, inMaxAutoFillCalculations); //default behavior 0412 computeStep2ForLayout(endLayout.grid, sizePerApplet, endNo, inMaxAutoFillCalculations); //default behavior 0413 0414 // console.log(" org.kde.latte s5..."); 0415 } 0416 0417 0418 function _updateSizeForAppletsInFill() { 0419 if (inNormalFillCalculationsState) { 0420 // console.log(" org.kde.latte -------------"); 0421 // console.log(" org.kde.latte s1..."); 0422 var noA = startLayout.fillApplets + mainLayout.fillApplets + endLayout.fillApplets; 0423 0424 if (noA === 0) { 0425 return; 0426 } 0427 0428 var use_maximum_length = true; 0429 0430 if (mainLayout.shownApplets === 0 || root.myView.alignment !== LatteCore.Types.Justify) { 0431 updateFillAppletsWithOneStep(use_maximum_length); 0432 updateFillAppletsWithOneStep(!use_maximum_length); 0433 } else { 0434 //! Justify mode in all remaining cases 0435 updateFillAppletsWithTwoSteps(use_maximum_length); 0436 updateFillAppletsWithTwoSteps(!use_maximum_length); 0437 } 0438 } 0439 } 0440 }