File indexing completed on 2024-11-24 05:00:31
0001 /* 0002 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org> 0003 SPDX-FileCopyrightText: 2022 Niccolò Venerandi <niccolo@venerandi.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 var layout; 0009 var root; 0010 var plasmoid; 0011 var marginHighlights; 0012 var appletsModel; 0013 0014 function addApplet(applet, x, y) { 0015 let appletItem = root.itemFor(applet); 0016 // don't show applet if it chooses to be hidden but still make it 0017 // accessible in the panelcontroller 0018 // Due to the nature of how "visible" propagates in QML, we need to 0019 // explicitly set it on the container (so the Layout ignores it) 0020 // as well as the applet (so it reliably knows about), otherwise it can 0021 // happen that an applet erroneously thinks it's visible, or suddenly 0022 // starts thinking that way on teardown (virtual desktop pager) 0023 // leading to crashes 0024 var middle, new_element = {applet: appletItem} 0025 0026 appletItem.visible = Qt.binding(function() { 0027 return applet.status !== PlasmaCore.Types.HiddenStatus || (!root.plasmoid.immutable && root.plasmoid.userConfiguring); 0028 }); 0029 0030 // Insert icons to the left of whatever is at the center (usually a Task Manager), 0031 // if it exists. 0032 // FIXME TODO: This is a real-world fix to produce a sensible initial position for 0033 // launcher icons added by launcher menu applets. The basic approach has been used 0034 // since Plasma 1. However, "add launcher to X" is a generic-enough concept and 0035 // frequent-enough occurrence that we'd like to abstract it further in the future 0036 // and get rid of the ugliness of parties external to the containment adding applets 0037 // of a specific type, and the containment caring about the applet type. In a better 0038 // system the containment would be informed of requested launchers, and determine by 0039 // itself what it wants to do with that information. 0040 if (applet.pluginName === "org.kde.plasma.icon" && x === 0 && y === 0 && 0041 (middle = currentLayout.childAt(root.width / 2, root.height / 2))) { 0042 appletsModel.insert(middle.index, new_element); 0043 // Fall through to determining an appropriate insert position. 0044 } else if (x >= 0 && y >= 0) { 0045 appletsModel.insert(indexAtCoordinates(x, y), new_element) 0046 } else { 0047 appletsModel.append(new_element); 0048 } 0049 updateMargins(); 0050 } 0051 0052 function restore() { 0053 var configString = String(root.plasmoid.configuration.AppletOrder) 0054 0055 //array, a cell for encoded item order 0056 var itemsArray = configString.split(";"); 0057 0058 //map applet id->order in panel 0059 var idsOrder = new Object(); 0060 //map order in panel -> applet pointer 0061 var appletsOrder = new Object(); 0062 0063 for (var i = 0; i < itemsArray.length; i++) { 0064 //property name: applet id 0065 //property value: order 0066 idsOrder[itemsArray[i]] = i; 0067 } 0068 0069 for (var i = 0; i < root.plasmoid.applets.length; ++i) { 0070 if (idsOrder[root.plasmoid.applets[i].id] !== undefined) { 0071 appletsOrder[idsOrder[root.plasmoid.applets[i].id]] = root.plasmoid.applets[i]; 0072 //ones that weren't saved in AppletOrder go to the end 0073 } else { 0074 appletsOrder["unordered"+i] = root.plasmoid.applets[i]; 0075 } 0076 } 0077 0078 //finally, restore the applets in the correct order 0079 for (var i in appletsOrder) { 0080 addApplet(appletsOrder[i], -1, -1) 0081 } 0082 //rewrite, so if in the orders there were now invalid ids or if some were missing creates a correct list instead 0083 save(); 0084 } 0085 0086 function save() { 0087 var ids = new Array(); 0088 for (var i = 0; i < layout.children.length; ++i) { 0089 var child = layout.children[i]; 0090 if (child.hasOwnProperty("applet") && child.applet) { 0091 ids.push(child.applet.plasmoid.id); 0092 } 0093 } 0094 root.plasmoid.configuration.AppletOrder = ids.join(';'); 0095 root.plasmoid.configuration.writeConfig(); 0096 updateMargins(); 0097 } 0098 0099 function childAtCoordinates(x, y) { 0100 if (root.isHorizontal) { 0101 y = layout.height / 2; 0102 } else { 0103 x = layout.width / 2; 0104 } 0105 /* 0106 * When adding a new panel, childAt will return lastSpacer, and that's where 0107 * `index` property works. 0108 */ 0109 var child = layout.childAt(x, y); 0110 while (!child) { 0111 if (root.isHorizontal) { 0112 // Only yields incorrect results for widgets smaller than the 0113 // row/column spacing, which is luckly fairly unrealistic 0114 x -= layout.rowSpacing 0115 } else { 0116 y -= layout.columnSpacing 0117 } 0118 if (x < 0 || y < 0) { 0119 return 0; 0120 } 0121 child = layout.childAt(x, y); 0122 } 0123 return child 0124 } 0125 0126 function indexAtCoordinates(x, y) { 0127 let child = childAtCoordinates(x, y) 0128 if ((root.plasmoid.formFactor === 3 && y < child.y + child.height/2) || 0129 (root.plasmoid.formFactor !== 3 && x < child.x + child.width/2)) { 0130 return child.index; 0131 } else { 0132 return child.index+1; 0133 } 0134 } 0135 0136 function updateMargins() { 0137 var inThickArea = false; 0138 for (var i = 0; i < appletsModel.count; ++i) { 0139 var child = appletsModel.get(i).applet.parent 0140 if (child.dragging) {child = child.dragging} 0141 child.inThickArea = inThickArea 0142 if (child.isMarginSeparator) { 0143 inThickArea = !inThickArea 0144 } 0145 } 0146 } 0147 0148 function move(applet, end) { 0149 var start = applet.index 0150 var target = end - (start < end) 0151 if (start == target) return; 0152 // Setting oldX,oldY allows for position animations 0153 for (let i = Math.min(start, end); i <= Math.max(start, end-1); i++) { 0154 let el = layout.children[i] 0155 el.oldX = el.x, el.oldY = el.y 0156 } 0157 appletsModel.move(start, target, 1) 0158 save() 0159 }