diff --git a/containment/package/contents/ui/editmode/ConfigOverlay.qml b/containment/package/contents/ui/editmode/ConfigOverlay.qml index 237a2208..5a3439cf 100644 --- a/containment/package/contents/ui/editmode/ConfigOverlay.qml +++ b/containment/package/contents/ui/editmode/ConfigOverlay.qml @@ -1,558 +1,566 @@ /* * Copyright 2016 Smith AR * 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 . */ import QtQuick 2.7 import QtQuick.Layouts 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 MouseArea { id: configurationArea z: 1000 width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.width : thickness height: plasmoid.formFactor === PlasmaCore.Types.Vertical ? root.height : thickness visible: root.inConfigureAppletsMode hoverEnabled: root.inConfigureAppletsMode focus: true cursorShape: { if (currentApplet && tooltip.visible && currentApplet.latteStyleApplet) { return root.isHorizontal ? Qt.SizeHorCursor : Qt.SizeVerCursor; } return Qt.ArrowCursor; } property bool isResizingLeft: false property bool isResizingRight: false property Item currentApplet property Item previousCurrentApplet + property Item currentHoveredLayout: { + if (placeHolder.parent !== configurationArea) { + return placeHolder.parent; + } + + return currentApplet ? currentApplet.parent : null + } + property int lastX property int lastY property int appletX property int appletY readonly property int thickness: visibilityManager.thicknessNormalOriginalValue - visibilityManager.extraNormalThickMask - 1 readonly property int spacerHandleSize: units.smallSpacing onHeightChanged: tooltip.visible = false; onWidthChanged: tooltip.visible = false; function hoveredItem(x, y) { //! main layout var relevantLayout = mapFromItem(layoutsContainer.mainLayout,0,0); var item = layoutsContainer.mainLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); if (!item) { // start layout relevantLayout = mapFromItem(layoutsContainer.startLayout,0,0); item = layoutsContainer.startLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); } if (!item) { relevantLayout = mapFromItem(layoutsContainer.endLayout,0,0); item = layoutsContainer.endLayout.childAt(x-relevantLayout.x, y-relevantLayout.y); } return item; } function relevantLayoutForApplet(curapplet) { var relevantLayout; if (curapplet.parent === layoutsContainer.mainLayout) { relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0); } else if (curapplet.parent === layoutsContainer.startLayout) { relevantLayout = mapFromItem(layoutsContainer.startLayout, 0, 0); } else if (curapplet.parent === layoutsContainer.endLayout) { relevantLayout = mapFromItem(layoutsContainer.endLayout, 0, 0); } return relevantLayout; } onPositionChanged: { if (pressed) { var padding = units.gridUnit * 3; if (currentApplet && (mouse.x < -padding || mouse.y < -padding || mouse.x > width + padding || mouse.y > height + padding)) { var newCont = plasmoid.containmentAt(mouse.x, mouse.y); if (newCont && newCont != plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, mouse.x, mouse.y); newCont.addApplet(currentApplet.applet, newPos.x, newPos.y); root.dragOverlay.currentApplet = null; return; } } if(currentApplet){ if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.y += (mouse.y - lastY); // handle.y = currentApplet.y; } else { currentApplet.x += (mouse.x - lastX); // handle.x = currentApplet.x; } } lastX = mouse.x; lastY = mouse.y; var item = hoveredItem(mouse.x, mouse.y); if (item && item !== placeHolder) { placeHolder.parent = configurationArea; var posInItem = mapToItem(item, mouse.x, mouse.y); if ((plasmoid.formFactor === PlasmaCore.Types.Vertical && posInItem.y < item.height/2) || (plasmoid.formFactor !== PlasmaCore.Types.Vertical && posInItem.x < item.width/2)) { root.layoutManagerInsertBefore(item, placeHolder); } else { root.layoutManagerInsertAfter(item, placeHolder); } } } else { var item = hoveredItem(mouse.x, mouse.y); if (root.dragOverlay && item && item !== lastSpacer) { root.dragOverlay.currentApplet = item; } else { currentApplet = null; root.dragOverlay.currentApplet = null; } } if (root.dragOverlay.currentApplet) { hideTimer.stop(); tooltip.visible = true; tooltip.raise(); } } onExited: hideTimer.restart(); onCurrentAppletChanged: { previousCurrentApplet = currentApplet; if (!currentApplet || !root.dragOverlay.currentApplet) { hideTimer.restart(); return; } var relevantLayout = relevantLayoutForApplet(currentApplet) ; if (!relevantLayout) { return; } handle.x = relevantLayout.x + currentApplet.x; handle.y = relevantLayout.y + currentApplet.y; handle.width = currentApplet.width; handle.height = currentApplet.height; lockButton.checked = currentApplet.lockZoom; colorizingButton.checked = !currentApplet.userBlocksColorizing; repositionHandler.restart(); } onPressed: { if (!root.dragOverlay.currentApplet) { return; } var relevantApplet = mapFromItem(currentApplet, 0, 0); var rootArea = mapFromItem(root, 0, 0); appletX = mouse.x - relevantApplet.x + rootArea.x; appletY = mouse.y - relevantApplet.y + rootArea.y; lastX = mouse.x; lastY = mouse.y; placeHolder.width = currentApplet.width; placeHolder.height = currentApplet.height; handle.width = currentApplet.width; handle.height = currentApplet.height; root.layoutManagerInsertBefore(currentApplet, placeHolder); currentApplet.parent = root; currentApplet.x = lastX-appletX; currentApplet.y = lastY-appletY; currentApplet.z = 900; } onReleased: { if (!root.dragOverlay.currentApplet) { return; } if(currentApplet && currentApplet.applet){ if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { currentApplet.applet.configuration.length = handle.height; } else { currentApplet.applet.configuration.length = handle.width; } } configurationArea.isResizingLeft = false; configurationArea.isResizingRight = false; root.layoutManagerInsertBefore(placeHolder, currentApplet); placeHolder.parent = configurationArea; currentApplet.z = 1; var relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0); handle.x = relevantLayout.x + currentApplet.x; handle.y = relevantLayout.y + currentApplet.y; // handle.width = currentApplet.width; // handle.height = currentApplet.height; root.layoutManagerSave(); root.layoutManagerMoveAppletsBasedOnJustifyAlignment(); layouter.updateSizeForAppletsInFill(); } onWheel: { if (!currentApplet || !currentApplet.latteStyleApplet) { return; } var angle = wheel.angleDelta.y / 8; if (angle > 12) currentApplet.latteStyleApplet.increaseLength(); else if (angle < 12) currentApplet.latteStyleApplet.decreaseLength(); } Item { id: placeHolder visible: configurationArea.containsMouse Layout.fillWidth: currentApplet ? currentApplet.Layout.fillWidth : false Layout.fillHeight: currentApplet ? currentApplet.Layout.fillHeight : false readonly property bool isPlaceHolder: true } //Because of the animations for the applets the handler can not catch up to //reposition itself when the currentApplet position or size changes. //This timer fixes that situation Timer { id: repositionHandler interval: 100 onTriggered: handle.updatePlacement(); } Timer { id: hideTimer interval: animations.duration.large * 2 onTriggered: { if (!tooltipMouseArea.containsMouse) { tooltip.visible = false; currentApplet = null; } } } Connections { target: currentApplet onXChanged: handle.updatePlacement(); onYChanged: handle.updatePlacement(); onWidthChanged: handle.updatePlacement(); onHeightChanged: handle.updatePlacement() } Item { id: handle visible: currentApplet && (configurationArea.containsMouse || tooltipMouseArea.containsMouse) //BEGIN functions function updatePlacement(){ if(currentApplet){ var transformChoords = configurationArea.mapFromItem(currentApplet, 0, 0) handle.x = transformChoords.x; handle.y = transformChoords.y; handle.width = currentApplet.width; handle.height = currentApplet.height; repositionHandler.restart(); } } //END functions Item { id: handleVisualItem width: root.isHorizontal ? parent.width : thickness height: root.isHorizontal ? thickness : parent.height readonly property int thickness: root.isHorizontal ? parent.height - metrics.margin.screenEdge : parent.width - metrics.margin.screenEdge Rectangle{ anchors.fill: parent color: theme.backgroundColor radius: 3 opacity: 0.5 } PlasmaCore.IconItem { source: "transform-move" width: Math.min(parent.width, parent.height) height: width anchors.centerIn: parent opacity: 0.5 } states:[ State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: handleVisualItem; anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } PropertyChanges{ target: handleVisualItem; anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] } Behavior on opacity { NumberAnimation { duration: animations.duration.large easing.type: Easing.InOutQuad } } } PlasmaCore.Dialog { id: tooltip visualParent: currentApplet type: PlasmaCore.Dialog.Dock flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.BypassWindowManagerHint | Qt.ToolTip location: plasmoid.location onVisualParentChanged: { if (visualParent && currentApplet && (currentApplet.applet || currentApplet.isSeparator || currentApplet.isInternalViewSplitter)) { configureButton.visible = !currentApplet.isInternalViewSplitter && (currentApplet.applet.pluginName !== root.plasmoidName) && currentApplet.applet.action("configure") && currentApplet.applet.action("configure").enabled; closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled; lockButton.visible = !currentApplet.isInternalViewSplitter && (currentApplet.applet.pluginName !== root.plasmoidName) && !currentApplet.isSeparator; colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter; label.text = currentApplet.isInternalViewSplitter ? i18n("Justify Splitter") : currentApplet.applet.title; } } mainItem: MouseArea { id: tooltipMouseArea enabled: currentApplet width: handleRow.childrenRect.width + (2 * handleRow.spacing) height: Math.max(configureButton.height, label.contentHeight, closeButton.height) hoverEnabled: true LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true onEntered: hideTimer.stop(); onExited: hideTimer.restart(); Row { id: handleRow anchors.horizontalCenter: parent.horizontalCenter spacing: 2*units.smallSpacing Row{ spacing: units.smallSpacing PlasmaComponents.ToolButton { id: configureButton anchors.verticalCenter: parent.verticalCenter iconSource: "configure" tooltip: i18n("Configure applet") onClicked: { tooltip.visible = false; currentApplet.applet.action("configure").trigger(); } } PlasmaComponents.Label { id: label anchors.verticalCenter: parent.verticalCenter anchors.rightMargin: units.smallSpacing textFormat: Text.PlainText maximumLineCount: 1 } Row{ spacing: units.smallSpacing/2 PlasmaComponents.ToolButton{ id: colorizingButton checkable: true iconSource: "color-picker" tooltip: i18n("Enable painting for this applet") onCheckedChanged: { currentApplet.userBlocksColorizing = !checked; root.layoutManagerSaveOptions(); } } PlasmaComponents.ToolButton{ id: lockButton checkable: true iconSource: checked ? "lock" : "unlock" tooltip: i18n("Disable parabolic effect for this applet") onCheckedChanged: { currentApplet.lockZoom = checked; root.layoutManagerSaveOptions(); } } PlasmaComponents.ToolButton { id: closeButton anchors.verticalCenter: parent.verticalCenter iconSource: "delete" tooltip: i18n("Remove applet") onClicked: { tooltip.visible = false; if(currentApplet && currentApplet.applet) currentApplet.applet.action("remove").trigger(); } } } } } } } states: [ State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: configurationArea anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } }, State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: configurationArea anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } } ] } diff --git a/containment/package/contents/ui/layouts/AppletsContainer.qml b/containment/package/contents/ui/layouts/AppletsContainer.qml index 2c50ad6b..4e0c31a1 100644 --- a/containment/package/contents/ui/layouts/AppletsContainer.qml +++ b/containment/package/contents/ui/layouts/AppletsContainer.qml @@ -1,222 +1,233 @@ /* * Copyright 2019 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 . */ import QtQuick 2.7 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import "./abilities" as Abilities Abilities.AbilityGrid { id: appletsContainer columns: root.isVertical ? 1 : 0 columnSpacing: 0 flow: isHorizontal ? Grid.LeftToRight : Grid.TopToBottom rows: root.isHorizontal ? 1 : 0 rowSpacing: 0 - //Layout.preferredWidth: width - //Layout.preferredHeight: height + opacity: { + if (root.inConfigureAppletsMode && root.panelAlignment===LatteCore.Types.Justify && layoutsContainer.mainLayout.isCoveredFromSideLayouts){ + if (dragOverlay && (!dragOverlay.currentHoveredLayout || dragOverlay.currentHoveredLayout === appletsContainer)) { + return 1; + } else { + return 0.3; + } + } + + return 1; + } + + readonly property int length : root.isHorizontal ? childrenRect.width : childrenRect.height; property int alignment: LatteCore.Types.BottomEdgeCenterAlign property int beginIndex: 0 property int offset: 0 //////////////////////////BEGIN states //user set Panel Positions // 0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom states: [ ///Left Edge State { name: "leftCenter" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: appletsContainer.offset; } }, State { name: "leftTop" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeTopAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.offset; anchors.bottomMargin:appletsContainer.lastMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "leftBottom" when: appletsContainer.alignment === LatteCore.Types.LeftEdgeBottomAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignLeft; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.lastMargin; anchors.bottomMargin:appletsContainer.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Right Edge State { name: "rightCenter" when: appletsContainer.alignment === LatteCore.Types.RightEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: appletsContainer.offset; } }, State { name: "rightTop" when: appletsContainer.alignment === LatteCore.Types.RightEdgeTopAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.offset; anchors.bottomMargin:appletsContainer.lastMargin; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "rightBottom" when: appletsContainer.alignment === LatteCore.Types.RightEdgeBottomAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignRight; verticalItemAlignment: Grid.AlignVCenter; anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:appletsContainer.lastMargin; anchors.bottomMargin:appletsContainer.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Bottom Edge State { name: "bottomCenter" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: appletsContainer.offset; anchors.verticalCenterOffset: 0; } }, State { name: "bottomLeft" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeLeftAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: appletsContainer.offset; anchors.rightMargin:appletsContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "bottomRight" when: appletsContainer.alignment === LatteCore.Types.BottomEdgeRightAlign AnchorChanges { target: appletsContainer anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignBottom anchors.leftMargin: appletsContainer.lastMargin; anchors.rightMargin:appletsContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Top Edge State { name: "topCenter" when: appletsContainer.alignment === LatteCore.Types.TopEdgeCenterAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: appletsContainer.offset; anchors.verticalCenterOffset: 0; } }, State { name: "topLeft" when: appletsContainer.alignment === LatteCore.Types.TopEdgeLeftAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: appletsContainer.offset; anchors.rightMargin:appletsContainer.lastMargin; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "topRight" when: appletsContainer.alignment === LatteCore.Types.TopEdgeRightAlign AnchorChanges { target: appletsContainer anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: appletsContainer; horizontalItemAlignment: Grid.AlignHCenter; verticalItemAlignment: Grid.AlignTop anchors.leftMargin: appletsContainer.lastMargin; anchors.rightMargin:appletsContainer.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] ////////////////END states } diff --git a/containment/package/contents/ui/layouts/LayoutsContainer.qml b/containment/package/contents/ui/layouts/LayoutsContainer.qml index 48f58701..369ec167 100644 --- a/containment/package/contents/ui/layouts/LayoutsContainer.qml +++ b/containment/package/contents/ui/layouts/LayoutsContainer.qml @@ -1,439 +1,456 @@ /* * Copyright 2016 Smith AR * 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 . */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.private.containment 0.1 as LatteContainment import "./abilities" as AbilitiesTypes import "../debug" as Debug Item{ id: layoutsContainer readonly property bool isHidden: root.inStartup || (latteView && latteView.visibility && latteView.visibility.isHidden) readonly property bool useMaxLength: plasmoid.configuration.alignment === LatteCore.Types.Justify property int currentSpot: -1000 readonly property alias startLayout : _startLayout readonly property alias mainLayout: _mainLayout readonly property alias endLayout: _endLayout readonly property AbilitiesTypes.AbilityLayouts applets: AbilitiesTypes.AbilityLayouts{ startLayout: _startLayout mainLayout: _mainLayout endLayout: _endLayout } signal contentsLengthChanged(); Binding { target: layoutsContainer property: "x" when: !visibilityManager.inLocationAnimation value: { if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isHorizontal && useMaxLength ){ return ((latteView.width/2) - (root.maxLength/2) + background.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isVertical){ return; } if (layoutsContainer.isHidden && root.isVertical) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } Binding{ target: layoutsContainer property: "y" when: !visibilityManager.inLocationAnimation value: { if (root.behaveAsPlasmaPanel) { return 0; } if ( latteView && root.isVertical && useMaxLength ) { return ((latteView.height/2) - (root.maxLength/2) + background.offset); } else { if ((visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) && root.isHorizontal){ return; } if (layoutsContainer.isHidden && root.isHorizontal) { if (LatteCore.WindowSystem.compositingActive) { return visibilityManager.slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return visibilityManager.slidingOutToPos + 1; } else { return visibilityManager.slidingOutToPos - 1; } } } else { return 0; } } } } width: root.isHorizontal && useMaxLength ? root.maxLength : parent.width height: root.isVertical && useMaxLength ? root.maxLength : parent.height z:10 property bool animationSent: false property bool shouldCheckHalfs: (plasmoid.configuration.alignment === LatteCore.Types.Justify) && (_mainLayout.children>1) property int contentsWidth: _startLayout.width + _mainLayout.width + _endLayout.width property int contentsHeight: _startLayout.height + _mainLayout.height + _endLayout.height onContentsWidthChanged: { if (root.isHorizontal){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.width + _mainLayout.width/2) >= root.maxLength/2 ); } if (latteView && ((contentsWidth >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.addEvent(layoutsContainer); } contentsLengthChanged(); delayUpdateMaskArea.start(); } } onContentsHeightChanged: { if (root.isVertical){ var firstHalfExited = false; var secondHalfExited = false; if (shouldCheckHalfs){ firstHalfExited = ( (_startLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); secondHalfExited = ( (_endLayout.height + _mainLayout.height/2) >= root.maxLength/2 ); } if (latteView && ((contentsHeight >= root.maxLength) || firstHalfExited || secondHalfExited)) { autosize.updateIconSize(); } if (!animationSent) { animationSent = true; animations.needLength.removeEvent(layoutsContainer); } contentsLengthChanged(); delayUpdateMaskArea.start(); } } onXChanged: root.updateEffectsArea(); onYChanged: root.updateEffectsArea(); EnvironmentActions { active: root.scrollAction !== LatteContainment.Types.ScrollNone || root.dragActiveWindowEnabled || root.closeActiveWindowEnabled alignment: _mainLayout.alignment } AppletsContainer { id: _startLayout beginIndex: 0 offset: background.totals.shadowsLength/2 //it is applied only in Justify when both background length shadows are drawn alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeLeftAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeLeftAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeTopAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeTopAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } AppletsContainer { id: _mainLayout z:10 //be on top of start and end layouts beginIndex: 100 offset: { if (inConfigureOffset!==0) { return inConfigureOffset; } if (background.hasBothLengthShadows && !centered) { //! it is used for Top/Bottom/Left/Right alignments when they show both background length shadows return background.offset + background.totals.shadowsLength/2; } return (root.panelAlignment === LatteCore.Types.Justify) ? 0 : background.offset } readonly property bool centered: (root.panelAlignment === LatteCore.Types.Center) || (root.panelAlignment === LatteCore.Types.Justify) readonly property bool reversed: Qt.application.layoutDirection === Qt.RightToLeft //! do not update during dragging/moving applets inConfigureAppletsMode readonly property bool offsetUpdateIsBlocked: ((root.dragOverlay && root.dragOverlay.pressed) || layouter.appletsInParentChange) + property bool isCoveredFromSideLayouts: false property int inConfigureOffset: 0 alignment: { if (plasmoid.location === PlasmaCore.Types.LeftEdge) { if (centered) return LatteCore.Types.LeftEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.LeftEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.LeftEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.RightEdge) { if (centered) return LatteCore.Types.RightEdgeCenterAlign; if (root.panelAlignment === LatteCore.Types.Top) return LatteCore.Types.RightEdgeTopAlign; if (root.panelAlignment === LatteCore.Types.Bottom) return LatteCore.Types.RightEdgeBottomAlign; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { if (centered) return LatteCore.Types.BottomEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.BottomEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.BottomEdgeRightAlign; } } if (plasmoid.location === PlasmaCore.Types.TopEdge) { if (centered) return LatteCore.Types.TopEdgeCenterAlign; if ((root.panelAlignment === LatteCore.Types.Left && !reversed) || (root.panelAlignment === LatteCore.Types.Right && reversed)) { return LatteCore.Types.TopEdgeLeftAlign; } if ((root.panelAlignment === LatteCore.Types.Right && !reversed) || (root.panelAlignment === LatteCore.Types.Left && reversed)) { return LatteCore.Types.TopEdgeRightAlign; } } return LatteCore.Types.BottomEdgeCenterAlign; } transitions: Transition { enabled: editModeVisual.plasmaEditMode AnchorAnimation { duration: 0.8 * animations.duration.proposed easing.type: Easing.OutCubic } } + Binding{ + target: _mainLayout + property:"isCoveredFromSideLayouts" + when: !_mainLayout.offsetUpdateIsBlocked && layouter.inNormalFillCalculationsState + value: { + if (!layouter.mainLayout.onlyInternalSplitters) { + //! one of side layouts goes underneath the main layout when the main layout contains valid applets + var limit = (root.maxLength - mainLayout.length)/2; + return ((startLayout.length > limit ) || (endLayout.length > limit)); + } + + //! start and end layouts length exceed the maximum length + return (startLayout.length + endLayout.length) > (root.maxLength); + } + } + Binding{ target: _mainLayout property:"inConfigureOffset" when: !_mainLayout.offsetUpdateIsBlocked && layouter.inNormalFillCalculationsState value: { if (!root.inConfigureAppletsMode || root.panelAlignment !== LatteCore.Types.Justify || !layouter.mainLayout.onlyInternalSplitters) { return 0; } var layoutMaxLength = root.maxLength / 2; - var startLength = root.isHorizontal ? startLayout.childrenRect.width : startLayout.childrenRect.height; - var endLength = root.isHorizontal ? endLayout.childrenRect.width : endLayout.childrenRect.height; - var mainLength = root.isHorizontal ? mainLayout.childrenRect.width : mainLayout.childrenRect.height; + if (_mainLayout.isCoveredFromSideLayouts) { + return layoutMaxLength - mainLayout.length/2; + } - if (startLength > layoutMaxLength) { - return (layoutMaxLength - endLength - mainLength/2); - } else if (endLength > layoutMaxLength) { - return -(layoutMaxLength - startLength - mainLength/2); + if (startLayout.length > layoutMaxLength) { + return (layoutMaxLength - endLayout.length - mainLayout.length/2); + } else if (endLayout.length > layoutMaxLength) { + return -(layoutMaxLength - startLayout.length - mainLayout.length/2); } return 0; } } } AppletsContainer { id: _endLayout beginIndex: 200 offset: background.totals.shadowsLength/2 //it is applied only in Justify when both background length shadows are drawn alignment: { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return LatteCore.Types.BottomEdgeRightAlign; case PlasmaCore.Types.TopEdge: return LatteCore.Types.TopEdgeRightAlign; case PlasmaCore.Types.LeftEdge: return LatteCore.Types.LeftEdgeBottomAlign; case PlasmaCore.Types.RightEdge: return LatteCore.Types.RightEdgeBottomAlign; } return LatteCore.Types.BottomEdgeLeftAlign; } } Connections { target: metrics onIconSizeAnimationEnded: delayUpdateMaskArea.start(); } //! Debug Elements Loader{ anchors.top: startLayout.top anchors.horizontalCenter: startLayout.horizontalCenter active: root.debugModeLayouter readonly property Item debugLayout: layouter.startLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ anchors.top: endLayout.top anchors.horizontalCenter: endLayout.horizontalCenter active: root.debugModeLayouter readonly property Item debugLayout: layouter.endLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ anchors.top: mainLayout.top anchors.horizontalCenter: mainLayout.horizontalCenter active: root.debugModeLayouter z:70 readonly property Item debugLayout: layouter.mainLayout sourceComponent: Debug.Tag{ background.color: "white" label.text: tagText label.color: "black" label.font.pointSize: 13 readonly property int layoutLength: root.isHorizontal ? debugLayout.grid.width : debugLayout.grid.height readonly property string tagText: { return "normal:" + debugLayout.shownApplets + " / fill:" + debugLayout.fillApplets + " / reg_len:" + debugLayout.sizeWithNoFillApplets + " / tot_len:"+layoutLength; } } } Loader{ anchors.top: mainLayout.top anchors.left: parent.left active: root.debugModeLayouter readonly property Item debugLayout: layoutsContainer sourceComponent: Debug.Tag{ background.color: "blue" label.text: tagText label.color: "yellow" label.font.pointSize: 13 label.font.bold: true readonly property int layoutLength: root.isHorizontal ? debugLayout.width : debugLayout.height readonly property int layoutsLength: { if (root.isVertical) { return layouter.startLayout.grid.height + layouter.mainLayout.grid.height + layouter.endLayout.grid.height; } return layouter.startLayout.grid.width + layouter.mainLayout.grid.width + layouter.endLayout.grid.width; } readonly property string tagText: { return "MAX:" + root.maxLength + " / TOT:"+layoutLength + " / LAYS:"+ layoutsLength; } } } //! This timer is needed in order to update mask area after ContentsWidth/Height and iconSize changes Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { animations.needLength.removeEvent(layoutsContainer); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("LayoutsContainer timer: delayUpdateMaskArea called..."); } } } }