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 }