/* * 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 //! 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); //console.log("s3..."); 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); } } } }