File indexing completed on 2025-01-26 05:06:18

0001 /*
0002     SPDX-FileCopyrightText: 2012-2013 Eike Hein <hein@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 .import org.kde.kirigami 2.20 as Kirigami
0008 
0009 const iconMargin = Math.round(Kirigami.Units.smallSpacing / 4);
0010 const labelMargin = Kirigami.Units.smallSpacing;
0011 
0012 function horizontalMargins() {
0013     const spacingAdjustment = (tasks.plasmoid.pluginName === "org.kde.plasma.icontasks") ? (Kirigami.Settings.tabletMode ? 3 : tasks.plasmoid.configuration.iconSpacing) : 1
0014     return (taskFrame.margins.left + taskFrame.margins.right) * (tasks.vertical ? 1 : spacingAdjustment);
0015 }
0016 
0017 function verticalMargins() {
0018     const spacingAdjustment = (tasks.plasmoid.pluginName === "org.kde.plasma.icontasks") ? (Kirigami.Settings.tabletMode ? 3 : tasks.plasmoid.configuration.iconSpacing) : 1
0019     return (taskFrame.margins.top + taskFrame.margins.bottom) * (tasks.vertical ? spacingAdjustment : 1);
0020 }
0021 
0022 function adjustMargin(height, margin) {
0023     var available = height - verticalMargins();
0024 
0025     if (available < Kirigami.Units.iconSizes.small) {
0026         return Math.floor((margin * (Kirigami.Units.iconSizes.small / available)) / 3);
0027     }
0028 
0029     return margin;
0030 }
0031 
0032 function launcherLayoutTasks() {
0033     return Math.round(tasksModel.logicalLauncherCount / Math.floor(preferredMinWidth() / launcherWidth()));
0034 }
0035 
0036 function launcherLayoutWidthDiff() {
0037     return (launcherLayoutTasks() * taskWidth()) - (tasksModel.logicalLauncherCount * launcherWidth());
0038 }
0039 
0040 function logicalTaskCount() {
0041     var count = (tasksModel.count - tasksModel.logicalLauncherCount) + launcherLayoutTasks();
0042 
0043     return Math.max(tasksModel.count ? 1 : 0, count);
0044 }
0045 
0046 function maxStripes() {
0047     var length = tasks.vertical ? tasks.width : tasks.height;
0048     var minimum = tasks.vertical ? preferredMinWidth() : preferredMinHeight();
0049 
0050     return Math.min(tasks.plasmoid.configuration.maxStripes, Math.max(1, Math.floor(length / minimum)));
0051 }
0052 
0053 function tasksPerStripe() {
0054     if (tasks.plasmoid.configuration.forceStripes) {
0055         return Math.ceil(logicalTaskCount() / maxStripes());
0056     } else {
0057         var length = tasks.vertical ? taskList.height : taskList.width;
0058         var minimum = tasks.vertical ? preferredMinHeight() : preferredMinWidth();
0059 
0060         return Math.floor(length / minimum);
0061     }
0062 }
0063 
0064 function calculateStripes() {
0065     var stripes = tasks.plasmoid.configuration.forceStripes ? tasks.plasmoid.configuration.maxStripes : Math.min(tasks.plasmoid.configuration.maxStripes, Math.ceil(logicalTaskCount() / tasksPerStripe()));
0066 
0067     return Math.min(stripes, maxStripes());
0068 }
0069 
0070 function full() {
0071     return (maxStripes() == calculateStripes());
0072 }
0073 
0074 function optimumCapacity(width, height) {
0075     var length = tasks.vertical ? height : width;
0076     var maximum = tasks.vertical ? preferredMaxHeight() : preferredMaxWidth();
0077 
0078     if (!tasks.vertical) {
0079         //  Fit more tasks in this case, that is possible to cut text, before combining tasks.
0080         return Math.ceil(length / maximum) * maxStripes() + 1;
0081     }
0082 
0083     return Math.floor(length / maximum) * maxStripes();
0084 }
0085 
0086 function layoutWidth() {
0087     if (tasks.plasmoid.configuration.forceStripes && !tasks.vertical) {
0088         return Math.min(tasks.width, Math.max(preferredMaxWidth(), tasksPerStripe() * preferredMaxWidth()));
0089     } else {
0090         return tasks.width;
0091     }
0092 }
0093 
0094 function layoutHeight() {
0095     if (tasks.plasmoid.configuration.forceStripes && tasks.vertical) {
0096         return Math.min(tasks.height, Math.max(preferredMaxHeight(), tasksPerStripe() * preferredMaxHeight()));
0097     } else {
0098         return tasks.height;
0099     }
0100 }
0101 
0102 function preferredMinWidth() {
0103     var width = launcherWidth();
0104 
0105     if (!tasks.vertical && !tasks.iconsOnly) {
0106       width +=
0107           (Kirigami.Units.smallSpacing * 2) +
0108           (Kirigami.Units.gridUnit * 8);
0109     }
0110 
0111     return width;
0112 }
0113 
0114 function preferredMaxWidth() {
0115     if (tasks.iconsOnly) {
0116         if (tasks.vertical) {
0117             return tasks.width + verticalMargins();
0118         } else {
0119             return tasks.height + horizontalMargins();
0120         }
0121     }
0122 
0123     if (tasks.plasmoid.configuration.groupingStrategy != 0 && !tasks.plasmoid.configuration.groupPopups && !tasks.iconsOnly) {
0124         return preferredMinWidth();
0125     }
0126 
0127     return Math.floor(preferredMinWidth() * 1.6);
0128 }
0129 
0130 function preferredMinHeight() {
0131     // TODO FIXME UPSTREAM: Port to proper font metrics for descenders once we have access to them.
0132     return Kirigami.Units.iconSizes.sizeForLabels + 4;
0133 }
0134 
0135 function preferredMaxHeight() {
0136     if (tasks.vertical) {
0137       return verticalMargins() +
0138              Math.min(
0139                  // Do not allow the preferred icon size to exceed the width of
0140                  // the vertical task manager.
0141                  tasks.width,
0142                  tasks.iconsOnly ? tasks.width :
0143                     Math.max(
0144                         Kirigami.Units.iconSizes.sizeForLabels,
0145                         Kirigami.Units.iconSizes.medium
0146                     )
0147              );
0148     } else {
0149       return verticalMargins() +
0150              Math.min(
0151                  Kirigami.Units.iconSizes.small * 3,
0152                  Kirigami.Units.iconSizes.sizeForLabels *
0153                      3);
0154     }
0155 }
0156 
0157 // Returns the number of 'm' characters whose joint width must be available in the task button label
0158 // so that the button text is rendered at all.
0159 function minimumMColumns() {
0160     return tasks.vertical ? 4 : 5;
0161 }
0162 
0163 function taskWidth() {
0164     if (tasks.vertical) {
0165         return Math.floor(taskList.width / calculateStripes());
0166     } else {
0167         if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) {
0168             return Math.floor(taskList.width / Math.ceil(logicalTaskCount() / maxStripes()));
0169         } else {
0170             return Math.min(preferredMaxWidth(), Math.floor(taskList.width / Math.min(logicalTaskCount(), tasksPerStripe())));
0171         }
0172     }
0173 }
0174 
0175 function taskHeight() {
0176     if (tasks.vertical) {
0177         if (full() && Math.max(1, logicalTaskCount()) > tasksPerStripe()) {
0178             return Math.floor(taskList.height / Math.ceil(logicalTaskCount() / maxStripes()));
0179         } else {
0180             return Math.min(preferredMaxHeight(), Math.floor(taskList.height / Math.min(logicalTaskCount(), tasksPerStripe())));
0181         }
0182     } else {
0183         return Math.floor(taskList.height / calculateStripes());
0184     }
0185 }
0186 
0187 function launcherWidth() {
0188     var baseWidth = tasks.vertical ? preferredMinHeight() : Math.min(tasks.height, Kirigami.Units.iconSizes.small * 3);
0189 
0190     return (baseWidth + horizontalMargins())
0191         - (adjustMargin(baseWidth, taskFrame.margins.top) + adjustMargin(baseWidth, taskFrame.margins.bottom));
0192 }
0193 
0194 function maximumContextMenuTextWidth() {
0195   return (Kirigami.Units.iconSizes.sizeForLabels * 28);
0196 }
0197 
0198 function layout(container) {
0199     var item;
0200     var stripes = calculateStripes();
0201     var taskCount = tasksModel.count - tasksModel.logicalLauncherCount;
0202     var width = taskWidth();
0203     var adjustedWidth = width;
0204     var height = taskHeight();
0205 
0206     if (!tasks.vertical && stripes == 1 && taskCount)
0207     {
0208         var shrink = ((tasksModel.count - tasksModel.logicalLauncherCount) * preferredMaxWidth())
0209             + (tasksModel.logicalLauncherCount * launcherWidth()) > taskList.width;
0210         width = Math.min(shrink ? width + Math.floor(launcherLayoutWidthDiff() / taskCount) : width,
0211             preferredMaxWidth());
0212     }
0213 
0214     for (var i = 0; i < container.count; ++i) {
0215         item = container.itemAt(i);
0216 
0217         if (!item) {
0218             continue;
0219         }
0220 
0221         adjustedWidth = width;
0222 
0223         if (!tasks.vertical && !tasks.iconsOnly && (tasks.plasmoid.configuration.separateLaunchers || stripes == 1)) {
0224             if (item.model && (item.model.IsLauncher
0225                 || (!tasks.plasmoid.configuration.separateLaunchers && item.model.IsStartup && item.model.HasLauncher))) {
0226                 adjustedWidth = launcherWidth();
0227             } else if (stripes > 1 && i == tasksModel.logicalLauncherCount) {
0228                 adjustedWidth += launcherLayoutWidthDiff();
0229             }
0230         }
0231 
0232         item.width = adjustedWidth;
0233         item.height = height;
0234         item.visible = true;
0235     }
0236 }