/* * Copyright 2021 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 QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.plasmoid 2.0 import org.kde.latte.core 0.2 as LatteCore import org.kde.latte.abilities.items 0.1 as AbilityItems Item{ id: abilityItem anchors.bottom: (parent && plasmoid.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined anchors.top: (parent && plasmoid.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined anchors.left: (parent && plasmoid.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined anchors.right: (parent && plasmoid.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined width: { if (!visible) return 0; if (isSeparator) { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { return abilityItem.abilities.metrics.totals.thickness + abilityItem.abilities.metrics.margin.screenEdge; } else { if (isSeparatorInRealLength || !abilityItem.abilities.parabolic.isEnabled) { return LatteCore.Environment.separatorLength+2*abilityItem.abilities.metrics.margin.length; } } return 0; } if (root.vertical) { return _parabolicItem.width; } else { return hiddenSpacerLeft.width + _parabolicItem.width + hiddenSpacerRight.width; } } height: { if (!visible) return 0; if (isSeparator) { if (!root.vertical) { return abilityItem.abilities.metrics.totals.thickness + abilityItem.abilities.metrics.margin.screenEdge; } else { if (isSeparatorInRealLength || !abilityItem.abilities.parabolic.isEnabled) { return LatteCore.Environment.separatorLength+2*abilityItem.abilities.metrics.margin.length; } } return 0; } if (root.vertical) { return hiddenSpacerLeft.height + abilityItem.parabolicItem.height + hiddenSpacerRight.height; } else { return _parabolicItem.height; } } property bool isSeparator: false property bool isSeparatorInRealLength: false property Item abilities: null property Item contentItem: null readonly property int iconOffsetX: indicatorBackLayer.level.requested.iconOffsetX readonly property int iconOffsetY: indicatorBackLayer.level.requested.iconOffsetY readonly property alias indicator: abilityIndicatorObj readonly property alias parabolicItem: _parabolicItem readonly property alias tooltipVisualParent: _parabolicItem.titleTooltipVisualParent Component.onCompleted: { if (contentItem) { contentItem.parent = _parabolicItem.contentItemContainer; } } onContentItemChanged: { if (contentItem) { contentItem.parent = _parabolicItem.contentItemContainer; } } //! separators flags readonly property bool tailItemIsSeparator: { if (isSeparator || index < 0 ) { return false; } var tail = index - 1; while(tail>=0 && abilityItem.abilities.indexer.hidden.indexOf(tail)>=0) { tail = tail - 1; } var hasTailItemSeparator = abilityItem.abilities.indexer.separators.indexOf(tail)>=0; if (!hasTailItemSeparator && itemIndex === abilityItem.abilities.indexer.firstVisibleItemIndex){ return abilityItem.abilities.indexer.tailAppletIsSeparator; } return hasTailItemSeparator; } readonly property bool headItemIsSeparator: { if (isSeparator || index < 0 ) { return false; } var head = index + 1; while(head>=0 && abilityItem.abilities.indexer.hidden.indexOf(head)>=0) { head = head + 1; } var hasHeadItemSeparator = abilityItem.abilities.indexer.separators.indexOf(head)>=0; if (!hasHeadItemSeparator && itemIndex === abilityItem.abilities.indexer.lastVisibleItemIndex){ return abilityItem.abilities.indexer.headAppletIsSeparator; } return hasHeadItemSeparator; } Behavior on opacity { NumberAnimation { duration: abilityItem.abilities.animations.speedFactor.current * abilityItem.abilities.animations.duration.large } } Loader{ anchors.fill: parent active: abilityItem.abilities.debug.graphicsEnabled sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" border.color: "blue" border.width: 1 } } Item{ id:separatorItem anchors.bottom: (plasmoid.location === PlasmaCore.Types.BottomEdge) ? parent.bottom : undefined anchors.top: (plasmoid.location === PlasmaCore.Types.TopEdge) ? parent.top : undefined anchors.left: (plasmoid.location === PlasmaCore.Types.LeftEdge) ? parent.left : undefined anchors.right: (plasmoid.location === PlasmaCore.Types.RightEdge) ? parent.right : undefined anchors.horizontalCenter: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? parent.horizontalCenter : undefined anchors.verticalCenter: plasmoid.formFactor === PlasmaCore.Types.Vertical ? parent.verticalCenter : undefined anchors.bottomMargin: (plasmoid.location === PlasmaCore.Types.BottomEdge) ? margin : 0 anchors.topMargin: (plasmoid.location === PlasmaCore.Types.TopEdge) ? margin : 0 anchors.leftMargin: (plasmoid.location === PlasmaCore.Types.LeftEdge) ? margin : 0 anchors.rightMargin: (plasmoid.location === PlasmaCore.Types.RightEdge) ? margin : 0 opacity: (separatorShadow.active) || forceHiddenState ? 0 : 0.4 visible: abilityItem.isSeparator width: plasmoid.formFactor === PlasmaCore.Types.Vertical ? abilityItem.abilities.metrics.iconSize : (isSeparatorInRealLength ? LatteCore.Environment.separatorLength+abilityItem.abilities.metrics.totals.lengthEdges: 1) height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? abilityItem.abilities.metrics.iconSize : (isSeparatorInRealLength ? LatteCore.Environment.separatorLength+abilityItem.abilities.metrics.totals.lengthEdges: 1) property bool forceHiddenState: false readonly property int margin: abilityItem.abilities.metrics.margin.screenEdge + abilityItem.abilities.metrics.margin.thickness Behavior on opacity { NumberAnimation { duration: abilityItem.abilities.animations.speedFactor.current * abilityItem.abilities.animations.duration.large } } Rectangle { anchors.centerIn: parent width: plasmoid.formFactor === PlasmaCore.Types.Vertical ? abilityItem.abilities.metrics.iconSize - 4 : 1 height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? abilityItem.abilities.metrics.iconSize - 4 : 1 color: enforceLattePalette ? latteBridge.palette.textColor : theme.textColor } } ///Shadow in separator Loader{ id: separatorShadow anchors.fill: separatorItem active: abilityItem.abilities.myView.itemShadow.isEnabled && isSeparator && graphicsSystem.isAccelerated opacity: separatorItem.forceHiddenState ? 0 : 0.4 Behavior on opacity { NumberAnimation { duration: abilityItem.abilities.animations.speedFactor.current * abilityItem.abilities.animations.duration.large } } sourceComponent: DropShadow{ anchors.fill: parent color: abilityItem.abilities.myView.itemShadow.shadowColor fast: true samples: 2 * radius source: separatorItem radius: abilityItem.abilities.myView.itemShadow.size verticalOffset: 2 } } Flow{ width: parent.width height: parent.height // a hidden spacer for the first element to add stability // IMPORTANT: hidden spacers must be tested on vertical !!! HiddenSpacer{ id:hiddenSpacerLeft} Item{ width: _parabolicItem.width height: _parabolicItem.height AbilityItems.IndicatorObject { id: abilityIndicatorObj animations: abilityItem.abilities.animations metrics: abilityItem.abilities.metrics host: abilityItem.abilities.indicators iconBackgroundColor: "transparent" iconGlowColor: "transparent" } //! Indicator Back Layer IndicatorLevel{ id: indicatorBackLayer level.isBackground: true level.indicator: abilityIndicatorObj Loader{ anchors.fill: parent active: abilityItem.abilities.debug.graphicsEnabled sourceComponent: Rectangle{ color: "transparent" border.width: 1 border.color: "purple" opacity: 0.4 } } } ParabolicItem{id: _parabolicItem} //! Indicator Front Layer IndicatorLevel{ id: indicatorFrontLayer level.isForeground: true level.indicator: abilityIndicatorObj } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{ id:hiddenSpacerRight; rightSpacer: true } }// Flow with hidden spacers inside Loader { id: parabolicEventsAreaLoader active: abilityItem.abilities.parabolic.isEnabled width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? abilityItem.width : abilityItem.abilities.metrics.mask.thickness.zoomedForItems height: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? abilityItem.abilities.metrics.mask.thickness.zoomedForItems : abilityItem.height z:10000 sourceComponent: ParabolicEventsArea{} states:[ State{ name: "top" when: plasmoid.location === PlasmaCore.Types.TopEdge AnchorChanges{ target: parabolicEventsAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined; } }, State{ name: "left" when: plasmoid.location === PlasmaCore.Types.LeftEdge AnchorChanges{ target: parabolicEventsAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined; } }, State{ name: "right" when: plasmoid.location === PlasmaCore.Types.RightEdge AnchorChanges{ target: parabolicEventsAreaLoader anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter; anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined; } }, State{ name: "bottom" when: plasmoid.location === PlasmaCore.Types.BottomEdge AnchorChanges{ target: parabolicEventsAreaLoader anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined; anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom; } } ] } }