diff --git a/app/view/indicatorinfo.cpp b/app/view/indicatorinfo.cpp index 9ee7fc81..64cc9979 100644 --- a/app/view/indicatorinfo.cpp +++ b/app/view/indicatorinfo.cpp @@ -1,113 +1,158 @@ /* * 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 . */ #include "indicatorinfo.h" namespace Latte { namespace ViewPart { namespace IndicatorPart { Info::Info(QObject *parent) : QObject(parent) { } Info::~Info() { } bool Info::needsIconColors() const { return m_needsIconColors; } void Info::setNeedsIconColors(bool needs) { if (m_needsIconColors == needs) { return; } m_needsIconColors = needs; emit needsIconColorsChanged(); } +bool Info::needsMouseEventCoordinates() const +{ + return m_needsMouseEventCoordinates; +} + +void Info::setNeedsMouseEventCoordinates(bool needs) +{ + if (m_needsMouseEventCoordinates == needs) { + return; + } + + m_needsMouseEventCoordinates = needs; + emit needsMouseEventCoordinatesChanged(); +} + +bool Info::providesClickedAnimation() const +{ + return m_providesClickedAnimation; +} + +void Info::setProvidesClickedAnimation(bool provides) +{ + if (m_providesClickedAnimation == provides) { + return; + } + + m_providesClickedAnimation = provides; + emit providesClickedAnimationChanged(); +} + +bool Info::providesHoveredAnimation() const +{ + return m_providesHoveredAnimation; +} + +void Info::setProvidesHoveredAnimation(bool provides) +{ + if (m_providesHoveredAnimation == provides) { + return; + } + + m_providesHoveredAnimation = provides; + emit providesHoveredAnimationChanged(); +} + bool Info::providesFrontLayer() const { return m_providesFrontLayer; } void Info::setProvidesFrontLayer(bool front) { if (m_providesFrontLayer == front) { return; } m_providesFrontLayer = front; emit providesFrontLayerChanged(); } int Info::extraMaskThickness() const { return m_extraMaskThickness; } void Info::setExtraMaskThickness(int thick) { if (m_extraMaskThickness == thick) { return; } m_extraMaskThickness = thick; emit extraMaskThicknessChanged(); } float Info::minLengthPadding() const { return m_minLengthPadding; } void Info::setMinLengthPadding(float padding) { if (m_minLengthPadding == padding) { return; } m_minLengthPadding = padding; emit minLengthPaddingChanged(); } float Info::minThicknessPadding() const { return m_minThicknessPadding; } void Info::setMinThicknessPadding(float padding) { if (m_minThicknessPadding == padding) { return; } m_minThicknessPadding = padding; emit minThicknessPaddingChanged(); } } } } diff --git a/app/view/indicatorinfo.h b/app/view/indicatorinfo.h index a5dd5c62..250a3bc6 100644 --- a/app/view/indicatorinfo.h +++ b/app/view/indicatorinfo.h @@ -1,85 +1,103 @@ /* * 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 . */ #ifndef VIEWINDICATORINFO_H #define VIEWINDICATORINFO_H // Qt #include namespace Latte { namespace ViewPart { namespace IndicatorPart { /** * Information provided by indicator itself in order to provide a nice experience **/ class Info: public QObject { Q_OBJECT Q_PROPERTY(bool needsIconColors READ needsIconColors WRITE setNeedsIconColors NOTIFY needsIconColorsChanged) + Q_PROPERTY(bool needsMouseEventCoordinates READ needsMouseEventCoordinates WRITE setNeedsMouseEventCoordinates NOTIFY needsMouseEventCoordinatesChanged) + Q_PROPERTY(bool providesClickedAnimation READ providesClickedAnimation WRITE setProvidesClickedAnimation NOTIFY providesClickedAnimationChanged) + Q_PROPERTY(bool providesHoveredAnimation READ providesHoveredAnimation WRITE setProvidesHoveredAnimation NOTIFY providesHoveredAnimationChanged) Q_PROPERTY(bool providesFrontLayer READ providesFrontLayer WRITE setProvidesFrontLayer NOTIFY providesFrontLayerChanged) Q_PROPERTY(int extraMaskThickness READ extraMaskThickness WRITE setExtraMaskThickness NOTIFY extraMaskThicknessChanged) Q_PROPERTY(float minLengthPadding READ minLengthPadding WRITE setMinLengthPadding NOTIFY minLengthPaddingChanged) Q_PROPERTY(float minThicknessPadding READ minThicknessPadding WRITE setMinThicknessPadding NOTIFY minThicknessPaddingChanged) public: Info(QObject *parent); virtual ~Info(); bool needsIconColors() const; void setNeedsIconColors(bool needs); + bool needsMouseEventCoordinates() const; + void setNeedsMouseEventCoordinates(bool needs); + + bool providesClickedAnimation() const; + void setProvidesClickedAnimation(bool provides); + + bool providesHoveredAnimation() const; + void setProvidesHoveredAnimation(bool provides); + bool providesFrontLayer() const; void setProvidesFrontLayer(bool front); int extraMaskThickness() const; void setExtraMaskThickness(int thick); float minLengthPadding() const; void setMinLengthPadding(float padding); float minThicknessPadding() const; void setMinThicknessPadding(float padding); signals: void extraMaskThicknessChanged(); void minLengthPaddingChanged(); void minThicknessPaddingChanged(); void needsIconColorsChanged(); + void needsMouseEventCoordinatesChanged(); + void providesClickedAnimationChanged(); + void providesHoveredAnimationChanged(); void providesFrontLayerChanged(); private: bool m_needsIconColors{false}; + bool m_needsMouseEventCoordinates{false}; + bool m_providesClickedAnimation{false}; + bool m_providesHoveredAnimation{false}; bool m_providesFrontLayer{false}; int m_extraMaskThickness{0}; float m_minLengthPadding{0}; float m_minThicknessPadding{0}; }; } } } #endif diff --git a/containment/package/contents/ui/applet/AppletItem.qml b/containment/package/contents/ui/applet/AppletItem.qml index 8bc2cf41..9fda2082 100644 --- a/containment/package/contents/ui/applet/AppletItem.qml +++ b/containment/package/contents/ui/applet/AppletItem.qml @@ -1,929 +1,932 @@ /* * 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 QtGraphicalEffects 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.plasma.extras 2.0 as PlasmaExtras import org.kde.kquickcontrolsaddons 2.0 import org.kde.latte 0.2 as Latte import "colorizer" as Colorizer import "communicator" as Communicator import "indicator" as Indicator Item { id: appletItem visible: false width: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeWidth height: isInternalViewSplitter && !root.inConfigureAppletsMode ? 0 : computeHeight + signal mousePressed(int x, int y); + property bool animationsEnabled: true property bool animationWasSent: false //protection flag for animation broadcasting property bool canBeHovered: true property bool canShowAppletNumberBadge: !isSeparator && !isHidden && !isLattePlasmoid && !isSpacer && !isInternalViewSplitter property bool inFillCalculations: false //temp record, is used in calculations for fillWidth,fillHeight applets property bool needsFillSpace: { //fill flag, it is used in calculations for fillWidth,fillHeight applets if (!applet || !applet.Layout || (applet && applet.pluginName === "org.kde.plasma.panelspacer")) return false; if (((root.isHorizontal && applet.Layout.fillWidth===true) || (root.isVertical && applet.Layout.fillHeight===true)) && (applet.status !== PlasmaCore.Types.HiddenStatus)) return true; else return false; } property bool userBlocksColorizing: false property bool appletBlocksColorizing: !communicator.latteSideColoringEnabled property bool appletBlocksParabolicEffect: communicator.parabolicEffectLocked property bool lockZoom: false property bool isActive: (isExpanded && applet.pluginName !== root.plasmoidName && applet.pluginName !== "org.kde.activeWindowControl" && applet.pluginName !== "org.kde.plasma.appmenu") property bool isExpanded: applet && applet.status >= PlasmaCore.Types.NeedsAttentionStatus && applet.status !== PlasmaCore.Types.HiddenStatus property bool isHidden: applet && applet.status === PlasmaCore.Types.HiddenStatus ? true : false property bool isInternalViewSplitter: (internalSplitterId > 0) property bool isLattePlasmoid: latteApplet !== null property bool isZoomed: false property bool isSeparator: applet && (applet.pluginName === "audoban.applet.separator" || applet.pluginName === "org.kde.latte.separator") property bool isSpacer: applet && (applet.pluginName === "org.kde.latte.spacer") property bool isSystray: applet && (applet.pluginName === "org.kde.plasma.systemtray" || applet.pluginName === "org.nomad.systemtray" ) property bool firstChildOfStartLayout: (index === layoutsContainer.startLayout.beginIndex) property bool lastChildOfEndLayout: ((index === layoutsContainer.endLayout.beginIndex+layoutsContainer.endLayout.count-1)&&(layoutsContainer.endLayout.count>1)) //applet is in starting edge /*property bool startEdge: index < layoutsContainer.endLayout.beginIndex ? (index === 0)&&(layoutsContainer.mainLayout.count > 1) : (index === layoutsContainer.endLayout.beginIndex)&&(layoutsContainer.endLayout.count > 1)*/ property bool startEdge: (index === layoutsContainer.startLayout.beginIndex) || (index === layoutsContainer.mainLayout.beginIndex) || (index === layoutsContainer.endLayout.beginIndex) //applet is in ending edge property bool endEdge: plasmoid.configuration.panelPosition !== Latte.Types.Justify ? (index === layoutsContainer.mainLayout.beginIndex + layoutsContainer.mainLayout.count - 1)&&(layoutsContainer.mainLayout.count>1) : (((index === layoutsContainer.startLayout.beginIndex+layoutsContainer.startLayout.count-2)&&(layoutsContainer.startLayout.count>2)) ||((index === layoutsContainer.mainLayout.beginIndex+layoutsContainer.mainLayout.count-2)&&(layoutsContainer.mainLayout.count>2)) ||((index === layoutsContainer.endLayout.beginIndex+layoutsContainer.endLayout.count-1)&&(layoutsContainer.endLayout.count>1))) readonly property bool originalAppletBehavior: (root.zoomFactor === 1 || !canBeHovered && !root.titleTooltips) || lockZoom readonly property bool isRectangled: communicator.overlayLatteIconIsActive property int animationTime: appliedDurationTime * (1.2 *units.shortDuration) property int hoveredIndex: layoutsContainer.hoveredIndex property int index: -1 property int maxWidth: root.isHorizontal ? root.height : root.width property int maxHeight: root.isHorizontal ? root.height : root.width property int internalSplitterId: 0 property int previousIndex: -1 property int sizeForFill: -1 //it is used in calculations for fillWidth,fillHeight applets property int spacersMaxSize: Math.max(0,Math.ceil(0.55 * root.iconSize) - root.lengthMargins) property int status: applet ? applet.status : -1 property real computeWidth: root.isVertical ? wrapper.width : hiddenSpacerLeft.width+wrapper.width+hiddenSpacerRight.width property real computeHeight: root.isVertical ? hiddenSpacerLeft.height + wrapper.height + hiddenSpacerRight.height : wrapper.height property string title: isInternalViewSplitter ? "Now Dock Splitter" : "" property Item applet: null property Item latteApplet: applet && (applet.pluginName === root.plasmoidName) ? (applet.children[0] ? applet.children[0] : null) : null property Item latteStyleApplet: applet && ((applet.pluginName === "org.kde.latte.spacer") || (applet.pluginName === "org.kde.latte.separator")) ? (applet.children[0] ? applet.children[0] : null) : null property Item appletWrapper: applet && ((applet.pluginName === root.plasmoidName) || isSystray) ? wrapper : wrapper.wrapperContainer property Item tooltipVisualParent: titleTooltipParent property Item communicatorAlias: communicator property Item wrapperAlias: wrapper property alias containsMouse: appletMouseArea.containsMouse property alias pressed: appletMouseArea.pressed /*onComputeHeightChanged: { if(index==0) console.log(computeHeight); }*/ transitions: Transition { ParentAnimation { NumberAnimation { properties: "x,y"; duration: 1000 } } } /// BEGIN functions function activateAppletForNeutralAreas(mouse){ //if the event is at the active indicator or spacers area then try to expand the applet, //unfortunately for other applets there is no other way to activate them yet //for example the icon-only applets var choords = mapToItem(appletItem.appletWrapper, mouse.x, mouse.y); if (choords.x<0 || choords.y<0 || choords.x>=appletItem.appletWrapper.width || choords.y>=appletItem.appletWrapper.height) { latteView.toggleAppletExpanded(applet.id); } } function checkIndex(){ index = -1; for(var i=0; i maxSize || applet.Layout.minimumWidth > maxOfMinSize)) || (applet && root.isVertical && (applet.height > maxSize || applet.Layout.minimumHeight > maxOfMinSize))) && (applet && applet.pluginName !== "org.kde.plasma.panelspacer" && (applet.pluginName !== "org.kde.latte.spacer")) && !communicator.canShowOverlaiedLatteIcon) || isSystray || appletItem.needsFillSpace) { appletItem.canBeHovered = false; } else{ appletItem.canBeHovered = true; } } } function slotDestroyInternalViewSplitters() { if (isInternalViewSplitter) { destroy(); } } //! pos in global root positioning function containsPos(pos) { var relPos = root.mapToItem(appletItem,pos.x, pos.y); if (relPos.x>=0 && relPos.x<=width && relPos.y>=0 && relPos.y<=height) return true; return false; } ///END functions //BEGIN connections onAppletChanged: { if (!applet) { destroy(); } } onHoveredIndexChanged:{ if ( (Math.abs(hoveredIndex-index) > 1) && (hoveredIndex !== -1) ) { wrapper.zoomScale = 1; } if (Math.abs(hoveredIndex-index) >= 1) { hiddenSpacerLeft.nScale = 0; hiddenSpacerRight.nScale = 0; } } onIndexChanged: { if (appletItem.latteApplet) { root.latteAppletPos = index; } if (isHidden) { parabolicManager.setHidden(previousIndex, index); } if (isSeparator) { parabolicManager.setSeparator(previousIndex, index); } if (index>-1) { previousIndex = index; } } onIsExpandedChanged: { if (isExpanded) { root.hideTooltipLabel(); } } onIsHiddenChanged: { if (isHidden) { parabolicManager.setHidden(-1, index); } else { parabolicManager.setHidden(index, -1); } } onIsSeparatorChanged: { if (isSeparator) { parabolicManager.setSeparator(-1, index); } else { parabolicManager.setSeparator(index, -1); } } onLatteAppletChanged: { if(appletItem.latteApplet){ root.latteApplet = appletItem.latteApplet; root.latteAppletContainer = appletItem; root.latteAppletPos = index; appletItem.latteApplet.latteView = root; appletItem.latteApplet.forceHidePanel = true; appletItem.latteApplet.signalAnimationsNeedBothAxis.connect(slotAnimationsNeedBothAxis); appletItem.latteApplet.signalAnimationsNeedLength.connect(slotAnimationsNeedLength); appletItem.latteApplet.signalAnimationsNeedThickness.connect(slotAnimationsNeedThickness); appletItem.latteApplet.signalActionsBlockHiding.connect(slotActionsBlockHiding); appletItem.latteApplet.signalPreviewsShown.connect(slotPreviewsShown); appletItem.latteApplet.clearZoomSignal.connect(titleTooltipDialog.hide); } } onNeedsFillSpaceChanged: checkCanBeHovered(); Component.onCompleted: { checkIndex(); root.updateIndexes.connect(checkIndex); root.clearZoomSignal.connect(clearZoom); root.destroyInternalViewSplitters.connect(slotDestroyInternalViewSplitters); } Component.onDestruction: { if (isSeparator){ parabolicManager.setSeparator(previousIndex, -1); } if (isHidden) parabolicManager.setHidden(previousIndex, -1); if(root.latteAppletPos>=0 && root.latteAppletPos === index){ root.latteApplet = null; root.latteAppletContainer = null; root.latteAppletPos = -1; } root.updateIndexes.disconnect(checkIndex); root.clearZoomSignal.disconnect(clearZoom); root.destroyInternalViewSplitters.disconnect(slotDestroyInternalViewSplitters); if (appletItem.latteApplet) { appletItem.latteApplet.signalAnimationsNeedBothAxis.disconnect(slotAnimationsNeedBothAxis); appletItem.latteApplet.signalAnimationsNeedLength.disconnect(slotAnimationsNeedLength); appletItem.latteApplet.signalAnimationsNeedThickness.disconnect(slotAnimationsNeedThickness); appletItem.latteApplet.signalActionsBlockHiding.disconnect(slotActionsBlockHiding); appletItem.latteApplet.signalPreviewsShown.disconnect(slotPreviewsShown); appletItem.latteApplet.clearZoomSignal.disconnect(titleTooltipDialog.hide); } } Connections{ target: root /* onGlobalDirectRenderChanged:{ if (root.globalDirectRender && restoreAnimation.running) { // console.log("CLEAR APPLET SCALE !!!!"); //restoreAnimation.stop(); //wrapper.zoomScale = 1; } }*/ onLatteAppletHoveredIndexChanged: { if ( (root.zoomFactor>1) && (root.latteAppletHoveredIndex >= 0) ){ var distance = 2; //for Tasks plasmoid distance of 2 is not always safe there are //cases that needs to be 3, when an internal separator there is //between the hovered task and the current applet if (root.hasInternalSeparator) { if (index < root.latteAppletPos) { var firstTaskIndex = root.latteApplet.parabolicManager.availableHigherIndex(0); distance = firstTaskIndex+2; } else if (index > root.latteAppletPos) { var lastTaskIndex = root.latteApplet.parabolicManager.availableLowerIndex(root.tasksCount-1); distance = root.tasksCount-1-lastTaskIndex+2; } } if(Math.abs(index-root.latteAppletPos+root.latteAppletHoveredIndex)>=Math.max(2,distance)) { appletItem.clearZoom(); } } } onSignalActivateEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.activateTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && (entryIndex === parabolicManager.pseudoAppletIndex(appletItem.index))) { latteView.toggleAppletExpanded(applet.id); } } onSignalNewInstanceForEntryAtIndex: { if (parabolicManager.pseudoIndexBelongsToLatteApplet(entryIndex) && appletItem.isLattePlasmoid) { latteApplet.newInstanceForTaskAtIndex(entryIndex - latteApplet.tasksBaseIndex); } else if (root.unifiedGlobalShortcuts && (entryIndex === parabolicManager.pseudoAppletIndex(appletItem.index))) { latteView.toggleAppletExpanded(applet.id); } } } Connections{ target: layoutsContainer onHoveredIndexChanged:{ //for applets it is safe to consider that a distance of 2 //is enough to clearZoom if ( (root.zoomFactor>1) && (layoutsContainer.hoveredIndex>=0) && (Math.abs(index-layoutsContainer.hoveredIndex)>=2)) appletItem.clearZoom(); if ((restoreAnimation.running) && (layoutsContainer.hoveredIndex !== -1)) { restoreAnimation.stop(); } } } Connections{ target: root onLatteAppletHoveredIndexChanged: { if ((restoreAnimation.running) && (root.latteAppletHoveredIndex !== -1)) { restoreAnimation.stop(); } } } ///END connections //! It is used for any communication needed with the underlying applet Communicator.Engine{ id: communicator //set up the overlayed appletItems and properties for when a overlaiedIconItem must be presented to the user //because the plasma widgets specific implementation breaks the Latte experience onOverlayLatteIconIsActiveChanged:{ if (!overlayLatteIconIsActive && applet.opacity===0) { applet.opacity = 1; wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } else if (overlayLatteIconIsActive && applet.opacity>0) { applet.opacity = 0; if (applet.pluginName === "org.kde.plasma.folder") { applet.parent = wrapper.containerForOverlayIcon; applet.anchors.fill = wrapper.containerForOverlayIcon; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } /* Rectangle{ anchors.fill: parent color: "transparent" border.color: "green" border.width: 1 }*/ MouseArea{ id: appletMouseAreaBottom anchors.fill: parent propagateComposedEvents: true visible: (!appletMouseArea.visible || !appletMouseArea.enabled) && !root.editMode && !originalAppletBehavior property bool pressed: false onPressed: { appletItem.activateAppletForNeutralAreas(mouse); pressed = true; mouse.accepted = false; } onReleased: { pressed = false; mouse.accepted = false; } } //! Main Applet Shown Area Flow{ id: appletFlow width: appletItem.computeWidth height: appletItem.computeHeight // a hidden spacer for the first element to add stability // IMPORTANT: hidden spacers must be tested on vertical !!! HiddenSpacer{id: hiddenSpacerLeft} Item { width: wrapper.width height: wrapper.height Indicator.Bridge{ id: indicatorBridge } //! Indicator Back Layer Indicator.Loader{ id: indicatorBackLayer level: Indicator.LevelOptions { isBackground: true bridge: indicatorBridge } } ItemWrapper{ id: wrapper TitleTooltipParent{ id: titleTooltipParent } } //! The Applet Colorizer Colorizer.Applet { id: appletColorizer anchors.fill: parent opacity: mustBeShown ? 1 : 0 readonly property bool mustBeShown: colorizerManager.mustBeShown && !appletItem.userBlocksColorizing && !appletItem.appletBlocksColorizing && !appletItem.isInternalViewSplitter Behavior on opacity { NumberAnimation { duration: 1.2 * root.animationTime easing.type: Easing.OutCubic } } } //! Indicator Front Layer Indicator.Loader{ id: indicatorFrontLayer level: Indicator.LevelOptions { isForeground: true bridge: indicatorBridge } } //! Applet Shortcut Visual Badge Item { anchors.centerIn: parent width: { if (root.isHorizontal) { return rectangled ? root.iconSize * wrapper.zoomScale : wrapper.width } else { return root.iconSize * wrapper.zoomScale } } height: { if (root.isHorizontal) { return root.iconSize * wrapper.zoomScale } else { return rectangled ? root.iconSize * wrapper.zoomScale : wrapper.height } } property bool rectangled: canBeHovered && !lockZoom ShortcutBadge{ anchors.fill: parent } } } // a hidden spacer on the right for the last item to add stability HiddenSpacer{id: hiddenSpacerRight; rightSpacer: true} }// Flow with hidden spacers inside //Busy Indicator PlasmaComponents.BusyIndicator { z: 1000 visible: applet && applet.busy running: visible anchors.centerIn: parent width: Math.min(parent.width, parent.height) height: width } //! The Launchers Area Indicator Rectangle{ anchors.fill: parent radius: root.iconSize/10 property color tempColor: "#aa222222" color: tempColor border.width: 1 border.color: "#ff656565" opacity: latteApplet && root.addLaunchersMessage ? 1 : 0 Behavior on opacity{ NumberAnimation { duration: 2*root.durationTime*appletItem.animationTime } } PlasmaExtras.Heading { width: parent.width height: parent.height text: i18n("Tasks Area") horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter wrapMode: Text.WordWrap elide: Text.ElideRight fontSizeMode: Text.Fit color: colorizerManager.textColor rotation: { if (root.isHorizontal) return 0; else if (plasmoid.location === PlasmaCore.Types.LeftEdge) return -90; else if (plasmoid.location === PlasmaCore.Types.RightEdge) return 90; } } } MouseArea{ id: appletMouseArea anchors.fill: parent enabled: applet && !latteApplet && canBeHovered && !originalAppletBehavior && !communicator.parabolicEffectLocked hoverEnabled: latteApplet ? false : true - propagateComposedEvents: true + // propagateComposedEvents: true //! a way must be found in order for this be enabled //! only to support springloading for plasma 5.10 //! also on this is based the tooltips behavior by enabling it //! plasma tooltips are disabled visible: applet && !appletItem.latteApplet && !originalAppletBehavior && !communicator.parabolicEffectLocked && canBeHovered && !appletItem.isSeparator property bool blockWheel: false property bool pressed: false onClicked: { pressed = false; mouse.accepted = false; } onEntered: { if (containsMouse && !originalAppletBehavior && !communicator.parabolicEffectLocked && appletItem.canBeHovered){ root.stopCheckRestoreZoomTimer(); } if (restoreAnimation.running) { restoreAnimation.stop(); } if (!(isSeparator || isSpacer)) { root.showTooltipLabel(appletItem, applet.title); } //console.log("entered applet:" + layoutsContainer.hoveredIndex); if (layoutsContainer.hoveredIndex === -1 && root.latteAppletHoveredIndex===-1) { root.startDirectRenderDelayerDuringEntering(); } if (!(root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)){ layoutsContainer.hoveredIndex = index; } if (originalAppletBehavior || communicator.parabolicEffectLocked || !canBeHovered) { return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (root.isHorizontal){ layoutsContainer.currentSpot = mouseX; wrapper.calculateScales(mouseX); } else{ layoutsContainer.currentSpot = mouseY; wrapper.calculateScales(mouseY); } } onExited:{ if (communicator.appletIconItemIsShown()) { communicator.setAppletIconItemActive(false); } root.hideTooltipLabel(); if (root.zoomFactor>1){ root.startCheckRestoreZoomTimer(); } } onPositionChanged: { // if(!pressed){ if (originalAppletBehavior || !canBeHovered) { mouse.accepted = false; return; } if (root.isHalfShown || (root.latteApplet && (root.latteApplet.noTasksInAnimation>0 || root.latteApplet.contextMenu))) { return; } if (layoutsContainer.hoveredIndex === -1 && root.latteAppletHoveredIndex===-1) { root.startDirectRenderDelayerDuringEntering(); } if (!(root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)){ layoutsContainer.hoveredIndex = index; } if (!root.globalDirectRender && !root.directRenderDelayerIsRunning) { root.setGlobalDirectRender(true); } if( ((wrapper.zoomScale == 1 || wrapper.zoomScale === root.zoomFactor) && !root.globalDirectRender) || root.globalDirectRender) { if (root.isHorizontal){ var step = Math.abs(layoutsContainer.currentSpot-mouse.x); if (step >= root.animationStep){ layoutsContainer.currentSpot = mouse.x; wrapper.calculateScales(mouse.x); } } else{ var step = Math.abs(layoutsContainer.currentSpot-mouse.y); if (step >= root.animationStep){ layoutsContainer.currentSpot = mouse.y; wrapper.calculateScales(mouse.y); } } } mouse.accepted = false; } onPressed: { + appletItem.mousePressed(mouse.x, mouse.y); appletItem.activateAppletForNeutralAreas(mouse); pressed = true; //! this is needed for some applets is order to be activated/deactivated correctly //! such case is the "Application Menu". (bug #928) mouse.accepted = false; } onReleased: { pressed = false; mouse.accepted = false; } onWheel: { if (isSeparator || !root.mouseWheelActions || blockWheel || (root.latteViewIsHidden || root.inSlidingIn || root.inSlidingOut)){ wheel.accepted = false; return; } var angle = wheel.angleDelta.y / 8; blockWheel = true; scrollDelayer.start(); if (angle > 12) { //positive direction if (!isExpanded) { latteView.toggleAppletExpanded(applet.id); } } else if (angle < -12) { //negative direction if (isExpanded) { latteView.toggleAppletExpanded(applet.id); } } } //! A timer is needed in order to handle also touchpads that probably //! send too many signals very fast. This way the signals per sec are limited. //! The user needs to have a steady normal scroll in order to not //! notice a annoying delay Timer{ id: scrollDelayer interval: 700 onTriggered: appletMouseArea.blockWheel = false; } } //BEGIN states states: [ State { name: "left" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "bottom" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: appletFlow anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined;} } }, State { name: "top" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: appletFlow anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined;} } } ] //END states //BEGIN animations ///////Restore Zoom Animation///// ParallelAnimation{ id: restoreAnimation PropertyAnimation { target: wrapper property: "zoomScale" to: 1 duration: 4 * appletItem.animationTime easing.type: Easing.InCubic } PropertyAnimation { target: hiddenSpacerLeft property: "nScale" to: 0 duration: 4 * appletItem.animationTime easing.type: Easing.InCubic } PropertyAnimation { target: hiddenSpacerRight property: "nScale" to: 0 duration: 4 * appletItem.animationTime easing.type: Easing.InCubic } } /////Clicked Animation///// SequentialAnimation{ id: clickedAnimation alwaysRunToEnd: true - running: (appletMouseArea.pressed || appletMouseAreaBottom.pressed) && (root.durationTime > 0) + running: (appletMouseArea.pressed || appletMouseAreaBottom.pressed) && (root.durationTime > 0) && !indicators.info.providesClickedAnimation onStopped: { appletMouseArea.pressed = false; appletMouseAreaBottom.pressed = false; } ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: -0.35 duration: units.longDuration easing.type: Easing.OutQuad } } ParallelAnimation{ PropertyAnimation { target: wrapper.clickedEffect property: "brightness" to: 0 duration: units.longDuration easing.type: Easing.OutQuad } } } //END animations } diff --git a/containment/package/contents/ui/applet/ItemWrapper.qml b/containment/package/contents/ui/applet/ItemWrapper.qml index 0e4362ad..05aecdb7 100644 --- a/containment/package/contents/ui/applet/ItemWrapper.qml +++ b/containment/package/contents/ui/applet/ItemWrapper.qml @@ -1,688 +1,688 @@ /* * 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 QtGraphicalEffects 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.latte 0.2 as Latte import "../../code/MathTools.js" as MathTools Item{ id: wrapper width: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isHorizontal) { return -1; } //! width for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isHorizontal) { if (root.panelAlignment !== Latte.Types.Justify) { var maximumValue = (applet.Layout.maximumWidth === Infinity) || applet.Layout.maximumWidth === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumWidth); var constrainedWidth = MathTools.bound(applet.Layout.minimumWidth, applet.Layout.preferredWidth, maximumValue); return root.editMode ? Math.max(constrainedWidth, root.iconSize) : constrainedWidth; } if(appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksWidth; } else { return scaledWidth; } } height: { if (appletItem.isInternalViewSplitter && !root.inConfigureAppletsMode) return 0; if (isSeparator && root.parabolicEffectEnabled && root.isVertical) { return -1; } //! height for applets that use fillWidth/fillHeight such plasma taskmanagers and AWC if (appletItem.needsFillSpace && root.isVertical) { if (root.panelAlignment !== Latte.Types.Justify) { var maximumValue = (applet.Layout.maximumHeight === Infinity) || applet.Layout.maximumHeight === -1 ? appletItem.sizeForFill : Math.min(appletItem.sizeForFill, applet.Layout.maximumHeight); var constrainedHeight = MathTools.bound(applet.Layout.minimumHeight, applet.Layout.preferredHeight, maximumValue); return root.editMode ? Math.max(constrainedHeight, root.iconSize) : constrainedHeight; } if (appletItem.sizeForFill>-1){ return appletItem.sizeForFill; } } if (appletItem.latteApplet) { return latteApplet.tasksHeight; } else { return scaledHeight; } } opacity: appletColorizer.mustBeShown ? 0 : 1 property bool disableScaleWidth: false property bool disableScaleHeight: false property bool editMode: root.editMode property int appletWidth: applet ? applet.width : -1 property int appletHeight: applet ? applet.height : -1 property int appletMinimumWidth: applet && applet.Layout ? applet.Layout.minimumWidth : -1 property int appletMinimumHeight: applet && applet.Layout ? applet.Layout.minimumHeight : -1 property int appletPreferredWidth: applet && applet.Layout ? applet.Layout.preferredWidth : -1 property int appletPreferredHeight: applet && applet.Layout ? applet.Layout.preferredHeight : -1 property int appletMaximumWidth: applet && applet.Layout ? applet.Layout.maximumWidth : -1 property int appletMaximumHeight: applet && applet.Layout ? applet.Layout.maximumHeight : -1 property int iconSize: root.iconSize property int marginWidth: root.isVertical ? root.thickMargins : (root.inFullJustify && (appletItem.firstChildOfStartLayout || appletItem.lastChildOfEndLayout ) ? 0 : root.lengthMargins) //Fitt's Law property int marginHeight: root.isHorizontal ? root.thickMargins : (root.inFullJustify && (appletItem.firstChildOfStartLayout || appletItem.lastChildOfEndLayout ) ? 0 : root.lengthMargins) //Fitt's Law property real scaledWidth: zoomScaleWidth * (layoutWidth + marginWidth) property real scaledHeight: zoomScaleHeight * (layoutHeight + marginHeight) property real zoomScaleWidth: disableScaleWidth ? 1 : zoomScale property real zoomScaleHeight: disableScaleHeight ? 1 : zoomScale property int layoutWidthResult: 0 property int layoutWidth property int layoutHeight property real center:root.isHorizontal ? (width + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 : (height + hiddenSpacerLeft.separatorSpace + hiddenSpacerRight.separatorSpace) / 2 property real zoomScale: 1 property int index: appletItem.index property Item wrapperContainer: _wrapperContainer property Item clickedEffect: _clickedEffect property Item containerForOverlayIcon: _containerForOverlayIcon property Item overlayIconLoader: _overlayIconLoader Behavior on opacity { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } // property int pHeight: applet ? applet.Layout.preferredHeight : -10 /*function debugLayouts(){ if(applet){ console.log("---------- "+ applet.pluginName +" ----------"); console.log("MinW "+applet.Layout.minimumWidth); console.log("PW "+applet.Layout.preferredWidth); console.log("MaxW "+applet.Layout.maximumWidth); console.log("FillW "+applet.Layout.fillWidth); console.log("-----"); console.log("MinH "+applet.Layout.minimumHeight); console.log("PH "+applet.Layout.preferredHeight); console.log("MaxH "+applet.Layout.maximumHeight); console.log("FillH "+applet.Layout.fillHeight); console.log("-----"); console.log("Real Applet Width: "+applet.width); console.log("Real Applet Height: "+applet.height); console.log("-----"); console.log("Real Wrapper Width: "+wrapper.width); console.log("Real Wrapper Height: "+wrapper.height); console.log("-----"); console.log("Can be hovered: " + canBeHovered); console.log("Icon size: " + root.iconSize); console.log("Thick Margins: " + root.thickMargins); console.log("Intern. Margins: " + (root.lengthIntMargin * 2)); console.log("Intern. Margins: " + (root.lengthExtMargin * 2)); console.log("Max hovered criteria: " + (root.iconSize + thickMargins)); console.log("-----"); console.log("LayoutW: " + layoutWidth); console.log("LayoutH: " + layoutHeight); } } onLayoutWidthChanged: { debugLayouts(); } onLayoutHeightChanged: { debugLayouts(); }*/ onAppletWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } } onAppletMinimumWidthChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutWidth(); } onAppletMinimumHeightChanged: { if(zoomScale === 1) { checkCanBeHovered(); } updateLayoutHeight(); } onAppletPreferredWidthChanged: updateLayoutWidth(); onAppletPreferredHeightChanged: updateLayoutHeight(); onAppletMaximumWidthChanged: updateLayoutWidth(); onAppletMaximumHeightChanged: updateLayoutHeight(); Connections { target: appletItem onCanBeHoveredChanged: { updateLayoutWidth(); updateLayoutHeight(); } } onIconSizeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onEditModeChanged: { updateLayoutWidth(); updateLayoutHeight(); } onZoomScaleChanged: { if ((zoomScale === root.zoomFactor) && !root.globalDirectRender) { root.setGlobalDirectRender(true); } if ((zoomScale > 1) && !appletItem.isZoomed) { appletItem.isZoomed = true; if (!animationWasSent) { root.slotAnimationsNeedBothAxis(1); animationWasSent = true; } } else if (zoomScale == 1) { appletItem.isZoomed = false; if (animationWasSent) { root.slotAnimationsNeedBothAxis(-1); animationWasSent = false; } } } Connections { target: root onIsVerticalChanged: { if (appletItem.latteApplet) { return; } wrapper.disableScaleWidth = false; wrapper.disableScaleHeight = false; if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } function updateLayoutHeight(){ if (appletItem.needsFillSpace && root.isVertical) { layoutsContainer.updateSizeForAppletsInFill(); return; } if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.editMode) layoutHeight = 0; else layoutHeight = root.iconSize; } else if(applet && applet.pluginName === "org.kde.plasma.panelspacer"){ layoutHeight = root.iconSize; } else if(appletItem.isSystray && root.isHorizontal){ layoutHeight = root.iconSize; } else{ if(applet && (applet.Layout.minimumHeight > root.iconSize) && root.isVertical && !canBeHovered && !communicator.overlayLatteIconIsActive){ layoutHeight = applet.Layout.minimumHeight; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumHeight < root.iconSize || applet.Layout.preferredHeight > root.iconSize || appletItem.originalAppletBehavior) && root.isVertical && !disableScaleWidth && !communicator.overlayLatteIconIsActive) { if (!appletItem.isSpacer) { disableScaleHeight = true; } //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumHeight < root.iconSize)){ layoutHeight = applet.Layout.maximumHeight; } else if (applet.Layout.minimumHeight > root.iconSize){ layoutHeight = applet.Layout.minimumHeight; } else if ((applet.Layout.preferredHeight > root.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredHeight > 0 )){ layoutHeight = applet.Layout.preferredHeight; } else{ layoutHeight = root.iconSize; } } else { layoutHeight = root.iconSize; } } } function updateLayoutWidth(){ if (appletItem.needsFillSpace && root.isHorizontal) { layoutsContainer.updateSizeForAppletsInFill(); return; } if (isLattePlasmoid) { return; } else if (appletItem.isInternalViewSplitter){ if(!root.editMode) layoutWidth = 0; else layoutWidth = root.iconSize; } else if(applet && applet.pluginName === "org.kde.plasma.panelspacer"){ layoutWidth = root.iconSize; } else if(appletItem.isSystray && root.isVertical){ layoutWidth = root.iconSize; } else{ if(applet && (applet.Layout.minimumWidth > root.iconSize) && root.isHorizontal && !canBeHovered && !communicator.overlayLatteIconIsActive){ layoutWidth = applet.Layout.minimumWidth; } //it is used for plasmoids that need to scale only one axis... e.g. the Weather Plasmoid else if(applet && ( applet.Layout.maximumWidth < root.iconSize || applet.Layout.preferredWidth > root.iconSize || appletItem.originalAppletBehavior) && root.isHorizontal && !disableScaleHeight && !communicator.overlayLatteIconIsActive){ if (!appletItem.isSpacer) { disableScaleWidth = true; } //this way improves performance, probably because during animation the preferred sizes update a lot if((applet.Layout.maximumWidth < root.iconSize)){ // return applet.Layout.maximumWidth; layoutWidth = applet.Layout.maximumWidth; } else if (applet.Layout.minimumWidth > root.iconSize){ layoutWidth = applet.Layout.minimumWidth; } else if ((applet.Layout.preferredWidth > root.iconSize) || (appletItem.originalAppletBehavior && applet.Layout.preferredWidth > 0 )){ layoutWidth = applet.Layout.preferredWidth; } else{ layoutWidth = root.iconSize; } } else{ layoutWidth = root.iconSize; } } } Item{ id:_wrapperContainer width:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal){ return wrapper.width; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutWidth; } else { if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { return parent.zoomScaleWidth * (root.iconSize + root.thickMargins); } else { return parent.zoomScaleWidth * wrapper.layoutWidth; } } } height:{ if (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isVertical){ return wrapper.height; } if (appletItem.isInternalViewSplitter) { return wrapper.layoutHeight; } else { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { return parent.zoomScaleHeight * (root.iconSize + root.thickMargins); } else { return parent.zoomScaleHeight * wrapper.layoutHeight; } } } opacity: appletShadow.active ? 0 : 1 anchors.centerIn: parent ///Secret MouseArea to be used by the folder widget Loader{ anchors.fill: parent active: communicator.overlayLatteIconIsActive && applet.pluginName === "org.kde.plasma.folder" sourceComponent: MouseArea{ onClicked: latteView.toggleAppletExpanded(applet.id); } } Item{ id: _containerForOverlayIcon anchors.fill: parent } Loader{ id: _overlayIconLoader anchors.fill: parent active: communicator.overlayLatteIconIsActive property color backgroundColor: "black" property color glowColor: "white" sourceComponent: Latte.IconItem{ id: overlayIconItem anchors.fill: parent source: { if (communicator.appletIconItemIsShown()) return communicator.appletIconItem.source; else if (communicator.appletImageItemIsShown()) return communicator.appletImageItem.source; return ""; } providesColors: indicators.info.needsIconColors && source != "" usesPlasmaTheme: communicator.appletIconItemIsShown() ? communicator.appletIconItem.usesPlasmaTheme : false Binding{ target: _overlayIconLoader property: "backgroundColor" when: overlayIconItem.providesColors value: overlayIconItem.backgroundColor } Binding{ target: _overlayIconLoader property: "glowColor" when: overlayIconItem.providesColors value: overlayIconItem.glowColor } Loader{ anchors.centerIn: parent active: root.debugModeOverloadedIcons sourceComponent: Rectangle{ width: 30 height: 30 color: "green" opacity: 0.65 } } } } } Loader{ anchors.fill: _wrapperContainer active: appletItem.isInternalViewSplitter && root.inConfigureAppletsMode rotation: root.isVertical ? 90 : 0 sourceComponent: PlasmaCore.SvgItem{ id:splitterImage anchors.fill: parent svg: PlasmaCore.Svg{ imagePath: root.universalSettings.splitterIconPath() } layer.enabled: true layer.effect: DropShadow { radius: root.appShadowSize fast: true samples: 2 * radius color: root.appShadowColor verticalOffset: 2 } Component.onCompleted: { if (root.isVertical) { wrapper.updateLayoutHeight(); wrapper.updateLayoutWidth(); } else { wrapper.updateLayoutWidth(); wrapper.updateLayoutHeight(); } } } } ///Shadow in applets Loader{ id: appletShadow anchors.fill: appletItem.appletWrapper active: appletItem.applet && !appletColorizer.mustBeShown && (((plasmoid.configuration.shadows === 1 /*Locked Applets*/ && (!appletItem.canBeHovered || (appletItem.originalAppletBehavior && (applet.pluginName !== root.plasmoidName))) ) || (plasmoid.configuration.shadows === 2 /*All Applets*/ && (applet.pluginName !== root.plasmoidName))) || (root.forceTransparentPanel && plasmoid.configuration.shadows>0 && applet.pluginName !== root.plasmoidName)) /*on forced transparent state*/ onActiveChanged: { if (active && !isSeparator) { wrapperContainer.opacity = 0; } else { wrapperContainer.opacity = 1; } } opacity: isSeparator ? 0.4 : 1 sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor //"#ff080808" fast: true samples: 2 * radius source: communicator.overlayLatteIconIsActive ? _wrapperContainer : appletItem.applet radius: shadowSize verticalOffset: root.forceTransparentPanel || root.forcePanelForBusyBackground ? 0 : 2 property int shadowSize : root.appShadowSize } } BrightnessContrast{ id:hoveredImage anchors.fill: _wrapperContainer source: _wrapperContainer - enabled: opacity != 0 ? true : false + enabled: !indicators.info.providesHoveredAnimation && opacity != 0 ? true : false opacity: appletMouseArea.containsMouse ? 1 : 0 brightness: 0.25 contrast: 0.15 Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } } BrightnessContrast { id: _clickedEffect anchors.fill: _wrapperContainer source: _wrapperContainer visible: clickedAnimation.running } /* onHeightChanged: { if ((index == 1)|| (index==3)){ console.log("H: "+index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } } onZoomScaleChanged:{ if ((index == 1)|| (index==3)){ console.log(index+" ("+zoomScale+"). "+currentLayout.children[1].height+" - "+currentLayout.children[3].height+" - "+(currentLayout.children[1].height+currentLayout.children[3].height)); } }*/ Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Rectangle{ anchors.fill: parent color: "transparent" //! red visualizer, in debug mode for the applets that use fillWidth or fillHeight //! green, for the rest border.color: (appletItem.needsFillSpace && (appletItem.sizeForFill>-1) && root.isHorizontal) ? "red" : "green" border.width: 1 } } Behavior on zoomScale { enabled: !root.globalDirectRender NumberAnimation { duration: 3 * appletItem.animationTime easing.type: Easing.OutCubic } } Behavior on zoomScale { enabled: root.globalDirectRender && !restoreAnimation.running NumberAnimation { duration: root.directRenderAnimationTime } } function calculateScales( currentMousePosition ){ if (root.zoomFactor===1) { return; } var distanceFromHovered = Math.abs(index - layoutsContainer.hoveredIndex); // A new algorithm trying to make the zoom calculation only once // and at the same time fixing glitches if ((distanceFromHovered == 0)&& (currentMousePosition > 0) ){ //use the new parabolicManager in order to handle all parabolic effect messages var scales = parabolicManager.applyParabolicEffect(index, currentMousePosition, center); /*if (root.latteApplet && Math.abs(index - root.latteAppletPos) > 2){ root.latteApplet.clearZoom(); }*/ //Left hiddenSpacer if(appletItem.startEdge){ hiddenSpacerLeft.nScale = scales.leftScale - 1; } //Right hiddenSpacer ///there is one more item in the currentLayout ???? if(appletItem.endEdge){ hiddenSpacerRight.nScale = scales.rightScale - 1; } zoomScale = root.zoomFactor; } } //scale function signalUpdateScale(nIndex, nScale, step){ if(appletItem && !appletItem.containsMouse && (appletItem.index === nIndex)){ if ( ((canBeHovered && !appletItem.originalAppletBehavior) || appletItem.latteApplet) && (applet && applet.status !== PlasmaCore.Types.HiddenStatus) //&& (index != currentLayout.hoveredIndex) ){ if(!appletItem.latteApplet){ if(nScale >= 0) zoomScale = nScale + step; else zoomScale = zoomScale + step; } } } } Component.onCompleted: { root.updateScale.connect(signalUpdateScale); } Component.onDestruction: { root.updateScale.disconnect(signalUpdateScale); } }// Main task area // id:wrapper diff --git a/containment/package/contents/ui/applet/indicator/Bridge.qml b/containment/package/contents/ui/applet/indicator/Bridge.qml index c34b30c6..fe2cb1aa 100644 --- a/containment/package/contents/ui/applet/indicator/Bridge.qml +++ b/containment/package/contents/ui/applet/indicator/Bridge.qml @@ -1,91 +1,101 @@ /* * 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.latte 0.2 as Latte Item{ id: indicatorBridge anchors.fill: parent property bool appletIsValid: true readonly property bool active: appletIsValid && ((indicators.isEnabled && appletItem.communicatorAlias.activeIndicatorEnabled && indicators.enabledForApplets) || (!indicators.enabledForApplets && appletItem.communicatorAlias.overlayLatteIconIsActive)) /* Indicators Properties in order use them*/ readonly property bool isTask: false readonly property bool isApplet: true readonly property bool isLauncher: false readonly property bool isStartup: false readonly property bool isWindow: false readonly property bool isActive: appletIsValid ? appletItem.isActive : false readonly property bool isGroup: false readonly property bool isHovered: appletIsValid ? appletMouseArea.containsMouse : false readonly property bool isMinimized: false readonly property bool isPressed: appletIsValid ? appletMouseArea.pressed : false readonly property bool inAttention: false readonly property bool inRemoving: false readonly property bool isRectangled: appletIsValid ? appletItem.isRectangled : true readonly property bool hasActive: isActive readonly property bool hasMinimized: false readonly property bool hasShown: false readonly property int windowsCount: 0 readonly property int windowsMinimizedCount: 0 readonly property int currentIconSize: root.iconSize readonly property int maxIconSize: root.maxIconSize readonly property int durationTime: root.durationTime readonly property real scaleFactor: appletIsValid ? appletItem.wrapperAlias.zoomScale : 1 readonly property real panelOpacity: root.currentPanelOpacity readonly property color shadowColor: root.appShadowColorSolid readonly property bool usePlasmaTabsStyle: !indicators.enabledForApplets readonly property QtObject palette: colorizerManager.applyTheme //!icon colors property color iconBackgroundColor: { if (appletIsValid) { return isRectangled ? appletItem.wrapperAlias.overlayIconLoader.backgroundColor : colorizerManager.buttonFocusColor; } return "black"; } property color iconGlowColor:{ if (appletIsValid) { return isRectangled ? appletItem.wrapperAlias.overlayIconLoader.glowColor : colorizerManager.focusGlowColor; } return "white"; } //! grouped options readonly property Item shared: indicators readonly property QtObject configuration: indicators.configuration + + Connections { + target: appletIsValid /*&& indicators.info.needsMouseEventCoordinates*/ ? appletItem : null + onMousePressed: { + console.log(x + " _ " + y); + var fixedPos = level.mapFromItem(appletItem, x, y); + console.log("f: " + fixedPos.x + " _ " + fixedPos.y); + level.mousePressed(fixedPos.x, fixedPos.y); + } + } } diff --git a/containment/package/contents/ui/applet/indicator/LevelOptions.qml b/containment/package/contents/ui/applet/indicator/LevelOptions.qml index 31e4d5ee..fb570ae2 100644 --- a/containment/package/contents/ui/applet/indicator/LevelOptions.qml +++ b/containment/package/contents/ui/applet/indicator/LevelOptions.qml @@ -1,39 +1,41 @@ /* * 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.latte 0.2 as Latte Item { id: level + signal mousePressed(int x, int y); + property bool isBackground: true property bool isForeground: false property Item bridge onIsBackgroundChanged: { isForeground = !isBackground; } onIsForegroundChanged: { isBackground = !isForeground; } } diff --git a/containment/package/contents/ui/applet/indicator/Loader.qml b/containment/package/contents/ui/applet/indicator/Loader.qml index 7cf9362e..d891f72e 100644 --- a/containment/package/contents/ui/applet/indicator/Loader.qml +++ b/containment/package/contents/ui/applet/indicator/Loader.qml @@ -1,38 +1,78 @@ /* * 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 0.2 as Latte Loader { id: indicatorLoader - anchors.fill: parent + 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: root.isHorizontal ? parent.horizontalCenter : undefined + anchors.verticalCenter: root.isVertical ? parent.verticalCenter : undefined active: level.bridge && level.bridge.active && (level.isBackground || (level.isForeground && indicators.info.providesFrontLayer)) sourceComponent: { if (!indicators.enabledForApplets && appletItem.communicatorAlias.overlayLatteIconIsActive) { return indicators.plasmaStyleComponent; } return indicators.indicatorComponent; } + width: { + if (locked) { + return visualLockedWidth; + } + + return root.isHorizontal ? appletItem.wrapperAlias.width - 2*appletItem.wrapperAlias.zoomScale*root.lengthExtMargin : appletItem.wrapperAlias.width; + } + + height: { + if (locked) { + return visualLockedHeight; + } + + return root.vertical ? appletItem.wrapperAlias.height - 2*appletItem.wrapperAlias.zoomScale*root.lengthExtMargin : appletItem.wrapperAlias.height; + } + + readonly property bool locked: appletItem.lockZoom || root.zoomFactor === 1 + + property real visualLockedWidth: root.iconSize + root.internalWidthMargins + property real visualLockedHeight: root.iconSize + root.internalHeightMargins + + //! Communications !// + property Item level + + Connections { + target: appletItem + enabled: indicators.info.needsMouseEventCoordinates + onMousePressed: { + var fixedPos = indicatorLoader.mapFromItem(appletItem, x, y); + level.mousePressed(Math.round(fixedPos.x), Math.round(fixedPos.y)); + } + } } diff --git a/containment/package/contents/ui/indicators/Manager.qml b/containment/package/contents/ui/indicators/Manager.qml index 109e5cf9..5c2ad6cf 100644 --- a/containment/package/contents/ui/indicators/Manager.qml +++ b/containment/package/contents/ui/indicators/Manager.qml @@ -1,126 +1,157 @@ /* * 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.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte 0.2 as Latte import "../applet/indicator" as AppletIndicator Item{ id: managerIndicator readonly property QtObject configuration: latteView && latteView.indicator ? latteView.indicator.configuration : null readonly property bool isEnabled: latteView && latteView.indicator ? (latteView.indicator.enabled && latteView.indicator.pluginIsReady) : false readonly property bool enabledForApplets: latteView && latteView.indicator ? latteView.indicator.enabledForApplets : true readonly property bool reversed: latteView && latteView.indicator ? latteView.indicator.reversed : false readonly property real padding: Math.max(info.minLengthPadding, latteView && latteView.indicator ? latteView.indicator.padding : 0.08) readonly property string type: latteView && latteView.indicator ? latteView.indicator.type : "org.kde.latte.default" readonly property Component plasmaStyleComponent: latteView && latteView.indicator ? latteView.indicator.plasmaComponent : null readonly property Component indicatorComponent: latteView && latteView.indicator ? latteView.indicator.component : null readonly property Item info: Item{ readonly property bool needsIconColors: metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("needsIconColors") && metricsLoader.item.needsIconColors + + readonly property bool needsMouseEventCoordinates: metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("needsMouseEventCoordinates") + && metricsLoader.item.needsMouseEventCoordinates + readonly property bool providesFrontLayer: metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("providesFrontLayer") && metricsLoader.item.providesFrontLayer + readonly property bool providesHoveredAnimation: metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("providesHoveredAnimation") + && metricsLoader.item.providesHoveredAnimation + + readonly property bool providesClickedAnimation: metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("providesClickedAnimation") + && metricsLoader.item.providesClickedAnimation + readonly property int extraMaskThickness: { if (metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("extraMaskThickness")) { return metricsLoader.item.extraMaskThickness; } return 0; } readonly property real minThicknessPadding: { if (metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("minThicknessPadding")) { return metricsLoader.item.minThicknessPadding; } return 0; } readonly property real minLengthPadding: { if (metricsLoader.active && metricsLoader.item && metricsLoader.item.hasOwnProperty("minLengthPadding")) { return metricsLoader.item.minLengthPadding; } return 0; } } //! Metrics and values provided from an invisible indicator Loader{ id: metricsLoader opacity: 0 active: managerIndicator.isEnabled readonly property Item level: AppletIndicator.LevelOptions { isBackground: true bridge: AppletIndicator.Bridge{ appletIsValid: false } } sourceComponent: managerIndicator.indicatorComponent } //! Bindings in order to inform View::Indicator::Info Binding{ target: latteView && latteView.indicator ? latteView.indicator.info : null property:"needsIconColors" when: latteView && latteView.indicator value: managerIndicator.info.needsIconColors } + Binding{ + target: latteView && latteView.indicator ? latteView.indicator.info : null + property:"needsMouseEventCoordinates" + when: latteView && latteView.indicator + value: managerIndicator.info.needsMouseEventCoordinates + } + + Binding{ + target: latteView && latteView.indicator ? latteView.indicator.info : null + property:"providesClickedAnimation" + when: latteView && latteView.indicator + value: managerIndicator.info.providesClickedAnimation + } + + Binding{ + target: latteView && latteView.indicator ? latteView.indicator.info : null + property:"providesHoveredAnimation" + when: latteView && latteView.indicator + value: managerIndicator.info.providesHoveredAnimation + } + Binding{ target: latteView && latteView.indicator ? latteView.indicator.info : null property:"providesFrontLayer" when: latteView && latteView.indicator value: managerIndicator.info.providesFrontLayer } Binding{ target: latteView && latteView.indicator ? latteView.indicator.info : null property:"extraMaskThickness" when: latteView && latteView.indicator value: managerIndicator.info.extraMaskThickness } Binding{ target: latteView && latteView.indicator ? latteView.indicator.info : null property:"minLengthPadding" when: latteView && latteView.indicator value: managerIndicator.info.minLengthPadding } Binding{ target: latteView && latteView.indicator ? latteView.indicator.info : null property:"minThicknessPadding" when: latteView && latteView.indicator value: managerIndicator.info.minThicknessPadding } } diff --git a/containment/package/contents/ui/main.qml b/containment/package/contents/ui/main.qml index e9fdc3f0..9d4775ad 100644 --- a/containment/package/contents/ui/main.qml +++ b/containment/package/contents/ui/main.qml @@ -1,1919 +1,1925 @@ /* * 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 QtQuick.Window 2.2 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.kquickcontrolsaddons 2.0 import org.kde.draganddrop 2.0 as DragDrop import org.kde.plasma.plasmoid 2.0 import org.kde.latte 0.2 as Latte import "applet" as Applet import "colorizer" as Colorizer import "editmode" as EditMode import "indicators" as Indicators import "layouts" as Layouts import "../code/LayoutManager.js" as LayoutManager DragDrop.DropArea { id: root objectName: "containmentViewLayout" LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.isVertical LayoutMirroring.childrenInherit: true //// BEGIN SIGNALS signal clearZoomSignal(); signal destroyInternalViewSplitters(); signal emptyAreasWheel(QtObject wheel); signal separatorsUpdated(); signal signalActivateEntryAtIndex(int entryIndex); signal signalNewInstanceForEntryAtIndex(int entryIndex); signal updateEffectsArea(); signal updateIndexes(); signal updateScale(int delegateIndex, real newScale, real step); signal broadcastedToApplet(string pluginName, string action, variant value); //// END SIGNALS ////BEGIN properties property bool debugMode: Qt.application.arguments.indexOf("--graphics")>=0 property bool debugModeSpacers: Qt.application.arguments.indexOf("--spacers")>=0 property bool debugModeTimers: Qt.application.arguments.indexOf("--timers")>=0 property bool debugModeWindow: Qt.application.arguments.indexOf("--with-window")>=0 property bool debugModeOverloadedIcons: Qt.application.arguments.indexOf("--overloaded-icons")>=0 property bool globalDirectRender: false //it is used as a globalDirectRender for all elements in the dock property int directRenderAnimationTime: 0 property bool addLaunchersMessage: false property bool addLaunchersInTaskManager: plasmoid.configuration.addLaunchersInTaskManager // when there are only plasma style task managers OR any applets that fill width or height // the automatic icon size algorithm should better be disabled property bool autoDecreaseIconSize: !containsOnlyPlasmaTasks && layoutsContainer.fillApplets<=0 property bool backgroundOnlyOnMaximized: plasmoid.configuration.backgroundOnlyOnMaximized property bool behaveAsPlasmaPanel: { if (!latteView || !latteView.visibility) { return false; } return (visibilityManager.panelIsBiggerFromIconSize && (maxZoomFactor === 1.0) && (latteView.visibility.mode === Latte.Types.AlwaysVisible || latteView.visibility.mode === Latte.Types.WindowsGoBelow) && (plasmoid.configuration.panelPosition === Latte.Types.Justify)); } property int viewType: { if ((plasmoid.configuration.panelPosition === Latte.Types.Justify) && (plasmoid.configuration.useThemePanel) && (plasmoid.configuration.panelSize === 100) && (maxZoomFactor === 1.0)) { return Latte.Types.PanelView; } return Latte.Types.DockView; } property bool blurEnabled: plasmoid.configuration.blurEnabled && (!forceTransparentPanel || forcePanelForBusyBackground) property bool confirmedDragEntered: false property bool containsOnlyPlasmaTasks: false //this is flag to indicate when from tasks only a plasma based one is found property bool dockContainsMouse: latteView && latteView.visibility ? latteView.visibility.containsMouse : false property bool disablePanelShadowMaximized: plasmoid.configuration.disablePanelShadowForMaximized && Latte.WindowSystem.compositingActive property bool drawShadowsExternal: panelShadowsActive && behaveAsPlasmaPanel && !visibilityManager.inTempHiding property bool editMode: editModeVisual.inEditMode property bool windowIsTouching: latteView && latteView.windowsTracker && (latteView.windowsTracker.activeWindowTouching || hasExpandedApplet) property bool forceSolidPanel: (latteView && latteView.visibility && Latte.WindowSystem.compositingActive && !inConfigureAppletsMode && userShowPanelBackground && ( (plasmoid.configuration.solidBackgroundForMaximized && !(hasExpandedApplet && !plasmaBackgroundForPopups) && latteView.windowsTracker.existsWindowTouching) || (hasExpandedApplet && plasmaBackgroundForPopups) )) || !Latte.WindowSystem.compositingActive property bool forceTransparentPanel: root.backgroundOnlyOnMaximized && latteView && latteView.visibility && Latte.WindowSystem.compositingActive && !inConfigureAppletsMode && !forceSolidPanel && !(windowColors === Latte.Types.TouchingWindowColors && latteView.windowsTracker.activeWindowTouching) && !(windowColors === Latte.Types.ActiveWindowColors && latteView.windowsTracker.existsWindowActive) property bool forcePanelForBusyBackground: userShowPanelBackground && root.forceTransparentPanel && colorizerManager.mustBeShown && colorizerManager.backgroundIsBusy property int themeColors: plasmoid.configuration.themeColors property int windowColors: plasmoid.configuration.windowColors property bool colorizerEnabled: themeColors !== Latte.Types.PlasmaThemeColors || windowColors !== Latte.Types.NoneWindowColors property bool plasmaBackgroundForPopups: plasmoid.configuration.plasmaBackgroundForPopups readonly property bool hasExpandedApplet: plasmoid.applets.some(function (item) { return (item.status >= PlasmaCore.Types.NeedsAttentionStatus && item.status !== PlasmaCore.Types.HiddenStatus && item.pluginName !== root.plasmoidName && item.pluginName !== "org.kde.plasma.appmenu" && item.pluginName !== "org.kde.windowappmenu" && item.pluginName !== "org.kde.activeWindowControl"); }) readonly property bool hasUserSpecifiedBackground: (latteView && latteView.managedLayout && latteView.managedLayout.background.startsWith("/")) ? true : false readonly property bool inConfigureAppletsMode: root.editMode && (plasmoid.configuration.inConfigureAppletsMode || !Latte.WindowSystem.compositingActive) readonly property bool parabolicEffectEnabled: zoomFactor>1 && !inConfigureAppletsMode property bool dockIsShownCompletely: !(dockIsHidden || inSlidingIn || inSlidingOut) && !root.editMode property bool dragActiveWindowEnabled: plasmoid.configuration.dragActiveWindowEnabled property bool immutable: plasmoid.immutable property bool inFullJustify: (plasmoid.configuration.panelPosition === Latte.Types.Justify) && (plasmoid.configuration.maxLength===100) property bool inSlidingIn: visibilityManager ? visibilityManager.inSlidingIn : false property bool inSlidingOut: visibilityManager ? visibilityManager.inSlidingOut : false property bool inStartup: true property bool isHalfShown: false //is used to disable the zoom hovering effect at sliding in-out the dock property bool isHorizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal property bool isReady: !(dockIsHidden || inSlidingIn || inSlidingOut) property bool isVertical: !isHorizontal property bool isHovered: latteApplet ? ((latteAppletHoveredIndex !== -1) || (layoutsContainer.hoveredIndex !== -1)) //|| wholeArea.containsMouse : (layoutsContainer.hoveredIndex !== -1) //|| wholeArea.containsMouse property bool mouseWheelActions: plasmoid.configuration.mouseWheelActions property bool normalState : false property bool onlyAddingStarup: true //is used for the initialization phase in startup where there aren't removals, this variable provides a way to grow icon size property bool shrinkThickMargins: plasmoid.configuration.shrinkThickMargins property bool showLatteShortcutBadges: false property bool showAppletShortcutBadges: false property bool showMetaBadge: false property int applicationLauncherId: -1 //FIXME: possibly this is going to be the default behavior, this user choice //has been dropped from the Dock Configuration Window //property bool smallAutomaticIconJumps: plasmoid.configuration.smallAutomaticIconJumps property bool smallAutomaticIconJumps: true property bool userShowPanelBackground: Latte.WindowSystem.compositingActive ? plasmoid.configuration.useThemePanel : true property bool useThemePanel: noApplets === 0 || !Latte.WindowSystem.compositingActive ? true : (plasmoid.configuration.useThemePanel || plasmoid.configuration.solidBackgroundForMaximized) property alias hoveredIndex: layoutsContainer.hoveredIndex property alias directRenderDelayerIsRunning: directRenderDelayerForEnteringTimer.running property int actionsBlockHiding: 0 //actions that block hiding property int animationsNeedBothAxis:0 //animations need space in both axes, e.g zooming a task property int animationsNeedLength: 0 // animations need length, e.g. adding a task property int animationsNeedThickness: 0 // animations need thickness, e.g. bouncing animation property int animationTime: durationTime*2.8*units.longDuration property int automaticIconSizeBasedSize: -1 //it is not set, this is the defautl //what is the highest icon size based on what icon size is used, screen calculated or user specified property int maxIconSize: proportionIconSize!==-1 ? proportionIconSize : plasmoid.configuration.iconSize property int iconSize: automaticIconSizeBasedSize > 0 && autoDecreaseIconSize ? Math.min(automaticIconSizeBasedSize, root.maxIconSize) : root.maxIconSize property int proportionIconSize: { //icon size based on screen height if ((plasmoid.configuration.proportionIconSize===-1) || !latteView) return -1; return Math.max(16,Math.round(latteView.screenGeometry.height * plasmoid.configuration.proportionIconSize/100/8)*8); } property int iconStep: 8 property int latteAppletPos: -1 property int maxLength: { if (root.isHorizontal) { return behaveAsPlasmaPanel ? width : width * (plasmoid.configuration.maxLength/100) } else { return behaveAsPlasmaPanel ? height : height * (plasmoid.configuration.maxLength/100) } } property int leftClickAction: plasmoid.configuration.leftClickAction property int middleClickAction: plasmoid.configuration.middleClickAction property int hoverAction: plasmoid.configuration.hoverAction property int modifier: plasmoid.configuration.modifier property int modifierClickAction: plasmoid.configuration.modifierClickAction property int modifierClick: plasmoid.configuration.modifierClick property int scrollAction: plasmoid.configuration.scrollAction property bool panelOutline: plasmoid.configuration.panelOutline property int panelEdgeSpacing: Math.max(panelBoxBackground.lengthMargins, 1.5*appShadowSize) property int panelTransparency: plasmoid.configuration.panelTransparency //user set property int currentPanelTransparency: 0 //application override readonly property real currentPanelOpacity: currentPanelTransparency/100 property bool panelShadowsActive: { if (!userShowPanelBackground) { return false; } if (inConfigureAppletsMode) { return plasmoid.configuration.panelShadows; } //! Draw shadows for isBusy state only when current panelTransparency is greater than 40% if (plasmoid.configuration.panelShadows && root.forcePanelForBusyBackground && currentPanelTransparency>40) { return true; } if (( (plasmoid.configuration.panelShadows && !root.backgroundOnlyOnMaximized) || (plasmoid.configuration.panelShadows && root.backgroundOnlyOnMaximized && !root.forceTransparentPanel)) && !(disablePanelShadowMaximized && latteView && latteView.windowsTracker && latteView.windowsTracker.activeWindowMaximized)) { return true; } if (hasExpandedApplet && plasmaBackgroundForPopups) { return true; } return false; } property int appShadowOpacity: (plasmoid.configuration.shadowOpacity/100) * 255 property int appShadowSize: enableShadows ? (0.5*root.iconSize) * (plasmoid.configuration.shadowSize/100) : 0 property int appShadowSizeOriginal: enableShadows ? (0.5*maxIconSize) * (plasmoid.configuration.shadowSize/100) : 0 property string appChosenShadowColor: { if (plasmoid.configuration.shadowColorType === Latte.Types.ThemeColorShadow) { var strC = String(theme.textColor); return strC.indexOf("#") === 0 ? strC.substr(1) : strC; } else if (plasmoid.configuration.shadowColorType === Latte.Types.UserColorShadow) { return plasmoid.configuration.shadowColor; } // default shadow color return "080808"; } property string appShadowColor: "#" + decimalToHex(appShadowOpacity) + appChosenShadowColor property string appShadowColorSolid: "#" + appChosenShadowColor property int totalPanelEdgeSpacing: 0 //this is set by PanelBox //FIXME: this is not needed any more probably property int previousAllTasks: -1 //is used to forbid updateAutomaticIconSize when hovering property int offset: { /*if (behaveAsPlasmaPanel) { return 0; }*/ if (root.isHorizontal) { return width * (plasmoid.configuration.offset/100); } else { height * (plasmoid.configuration.offset/100) } } //center the layout correctly when the user uses an offset property int offsetFixed: (offset===0 || panelAlignment === Latte.Types.Center || plasmoid.configuration.panelPosition === Latte.Types.Justify)? offset : offset+panelMarginLength/2+totalPanelEdgeSpacing/2 property int realPanelSize: 0 property int realPanelLength: 0 property int realPanelThickness: 0 //this is set by the PanelBox property int panelThickMarginBase: 0 property int panelThickMarginHigh: 0 property int panelMarginLength: 0 property int panelShadow: 0 //shadowsSize property int editShadow: { if (!Latte.WindowSystem.compositingActive) { return 0; } else if (latteView && latteView.screenGeometry) { return latteView.screenGeometry.height/90; } else { return 7; } } property int themePanelThickness: { var panelBase = root.panelThickMarginHigh; var margin = shrinkThickMargins ? 0 : thickMargins; var maxPanelSize = (iconSize + margin) - panelBase; var percentage = Latte.WindowSystem.compositingActive ? plasmoid.configuration.panelSize/100 : 1; return Math.max(panelBase, panelBase + percentage*maxPanelSize); } property int lengthIntMargin: lengthIntMarginFactor * root.iconSize property int lengthExtMargin: lengthExtMarginFactor * root.iconSize property real lengthIntMarginFactor: indicators.isEnabled ? indicators.padding : 0 property real lengthExtMarginFactor: plasmoid.configuration.lengthExtMargin / 100 property real thickMarginFactor: { if (shrinkThickMargins) { return indicators.info.minThicknessPadding; } //0.075 old statesLineSize and 0.06 old default thickMargin return Math.max(indicators.info.minThicknessPadding, plasmoid.configuration.thickMargin / 100) } property int thickMargin: thickMarginFactor * root.iconSize //! thickness margins are always two and equal in order for items //! to be always correctly centered property int thickMargins: 2 * thickMargin //it is used in order to not break the calculations for the thickness placement //especially in automatic icon sizes calculations property int maxThickMargin: thickMarginFactor * maxIconSize property int lengthMargin: lengthIntMargin + lengthExtMargin property int lengthMargins: 2 * lengthMargin + property int widthMargins: root.isVertical ? thickMargins : lengthMargins + property int heightMargins: root.isHorizontal ? thickMargins : lengthMargins + + property int internalWidthMargins: root.isVertical ? thickMargins : 2 * lengthIntMargin + property int internalHeightMargins: root.isHorizontal ? thickMargins : 2 * lengthIntMargin + ///FIXME: I can't remember why this is needed, maybe for the anchorings!!! In order for the Double Layout to not mess the anchorings... //property int layoutsContainer.mainLayoutPosition: !plasmoid.immutable ? Latte.Types.Center : (root.isVertical ? Latte.Types.Top : Latte.Types.Left) //property int panelAlignment: plasmoid.configuration.panelPosition !== Latte.Types.Justify ? plasmoid.configuration.panelPosition : layoutsContainer.mainLayoutPosition property int panelAlignment: !root.inConfigureAppletsMode ? plasmoid.configuration.panelPosition : ( plasmoid.configuration.panelPosition === Latte.Types.Justify ? Latte.Types.Center : plasmoid.configuration.panelPosition ) property int panelUserSetAlignment: plasmoid.configuration.panelPosition property real zoomFactor: Latte.WindowSystem.compositingActive ? ( 1 + (plasmoid.configuration.zoomLevel / 20) ) : 1 readonly property string plasmoidName: "org.kde.latte.plasmoid" property var badgesForActivate: { if (!shortcutsEngine) { return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']; } return shortcutsEngine.badgesForActivate; } property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256] property Item dragOverlay property Item toolBox property Item latteAppletContainer property Item latteApplet readonly property Item indicatorsManager: indicators readonly property Item parabolicManager: _parabolicManager property QtObject latteView: null property QtObject shortcutsEngine: null property QtObject themeExtended: null property QtObject universalSettings: null property QtObject universalLayoutManager: null property QtObject managedLayout: latteView && latteView.managedLayout ? latteView.managedLayout : null // TO BE DELETED, if not needed: property int counter:0; ///BEGIN properties provided to Latte Plasmoid //shadows for applets, it should be removed as the appleitems don't need it any more property bool enableShadows: plasmoid.configuration.shadows || (root.forceTransparentPanel && plasmoid.configuration.shadows>0) property bool dockIsHidden: latteView ? latteView.visibility.isHidden : true property bool groupTasksByDefault: plasmoid.configuration.groupTasksByDefault property bool showInfoBadge: plasmoid.configuration.showInfoBadge property bool showProgressBadge: plasmoid.configuration.showProgressBadge property bool showAudioBadge: plasmoid.configuration.showAudioBadge property bool audioBadgeActionsEnabled: plasmoid.configuration.audioBadgeActionsEnabled property bool showWindowActions: plasmoid.configuration.showWindowActions property bool showWindowsOnlyFromLaunchers: plasmoid.configuration.showWindowsOnlyFromLaunchers property bool showOnlyCurrentScreen: plasmoid.configuration.showOnlyCurrentScreen property bool showOnlyCurrentDesktop: plasmoid.configuration.showOnlyCurrentDesktop property bool showOnlyCurrentActivity: plasmoid.configuration.showOnlyCurrentActivity property bool titleTooltips: plasmoid.configuration.titleTooltips property bool unifiedGlobalShortcuts: plasmoid.configuration.unifiedGlobalShortcuts readonly property bool hasInternalSeparator: latteApplet ? latteApplet.hasInternalSeparator : false property int animationStep: { if (!universalSettings || universalSettings.mouseSensitivity === Latte.Types.HighSensitivity) { return 1; } else if (universalSettings.mouseSensitivity === Latte.Types.MediumSensitivity) { return Math.max(3, root.iconSize / 18); } else if (universalSettings.mouseSensitivity === Latte.Types.LowSensitivity) { return Math.max(5, root.iconSize / 10); } } property int latteAppletHoveredIndex: latteApplet ? latteApplet.hoveredIndex : -1 property int launchersGroup: plasmoid.configuration.launchersGroup property int tasksCount: latteApplet ? latteApplet.tasksCount : 0 //! Animations property bool animationsEnabled: plasmoid.configuration.animationsEnabled && Latte.WindowSystem.compositingActive property bool animationLauncherBouncing: animationsEnabled && latteApplet && plasmoid.configuration.animationLauncherBouncing property bool animationWindowInAttention: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowInAttention property bool animationNewWindowSliding: animationsEnabled && latteApplet && plasmoid.configuration.animationNewWindowSliding property bool animationWindowAddedInGroup: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowAddedInGroup property bool animationWindowRemovedFromGroup: animationsEnabled && latteApplet && plasmoid.configuration.animationWindowRemovedFromGroup property real appliedDurationTime: animationsEnabled ? durationTime : 2 property real durationTime: { if (!animationsEnabled) { return 0; } /*if ((latteView && latteView.effects && latteView.effects.animationsBlocked) || !animationsEnabled) { return 0; }*/ if (plasmoid.configuration.durationTime === 0 || plasmoid.configuration.durationTime === 2 ) return plasmoid.configuration.durationTime; if (plasmoid.configuration.durationTime === 1) return 1.65; else if (plasmoid.configuration.durationTime === 3) return 2.35; return 2; } property real animationsZoomFactor : { if (!animationsEnabled) { return 1; } if (latteApplet && (animationLauncherBouncing || animationWindowInAttention || animationWindowAddedInGroup)) { return 1.65; } return 1; } property real maxZoomFactor: Math.max(zoomFactor, animationsZoomFactor) property rect screenGeometry: latteView ? latteView.screenGeometry : plasmoid.screenGeometry readonly property color minimizedDotColor: colorizerManager.minimizedDotColor ///END properties from latteApplet Plasmoid.backgroundHints: PlasmaCore.Types.NoBackground //// BEGIN properties in functions property int noApplets: { var count1 = 0; var count2 = 0; count1 = layoutsContainer.mainLayout.children.length; var tempLength = layoutsContainer.mainLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.mainLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count1--; } count2 = layoutsContainer.endLayout.children.length; tempLength = layoutsContainer.endLayout.children.length; for (var i=tempLength-1; i>=0; --i) { var applet = layoutsContainer.endLayout.children[i]; if (applet && (applet === dndSpacer || applet === lastSpacer || applet.isInternalViewSplitter)) count2--; } return (count1 + count2); } ///The index of user's current icon size property int currentIconIndex:{ for(var i=iconsArray.length-1; i>=0; --i){ if(iconsArray[i] === iconSize){ return i; } } return 3; } //// END properties in functions ////////////////END properties //// BEGIN OF Behaviors Behavior on thickMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthIntMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on lengthExtMargin { NumberAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } Behavior on iconSize { enabled: !(root.editMode && root.behaveAsPlasmaPanel) NumberAnimation { duration: 0.8 * root.animationTime onRunningChanged: { if (!running) { delayUpdateMaskArea.start(); } } } } Behavior on offset { enabled: editModeVisual.plasmaEditMode NumberAnimation { id: offsetAnimation duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } //// END OF Behaviors //////////////START OF CONNECTIONS onContainsOnlyPlasmaTasksChanged: updateAutomaticIconSize(); onEditModeChanged: { if (editMode) { visibilityManager.updateMaskArea(); updateAutomaticIconSize(); clearZoom(); } else { updateAutomaticIconSize(); layoutsContainer.updateSizeForAppletsInFill(); } //! This is used in case the dndspacer has been left behind //! e.g. the user drops a folder and a context menu is appearing //! but the user decides to not make a choice for the applet type if (dndSpacer.parent !== root) { dndSpacer.parent = root; } } onInConfigureAppletsModeChanged: { if (inConfigureAppletsMode && panelUserSetAlignment===Latte.Types.Justify) { joinLayoutsToMainLayout(); } else if (!inConfigureAppletsMode) { splitMainLayoutToLayouts(); } updateIndexes(); } //! It is used only when the user chooses different alignment types //! and not during startup onPanelUserSetAlignmentChanged: { if (!root.editMode) { return; } if (!inConfigureAppletsMode){ if (panelUserSetAlignment===Latte.Types.Justify) { addInternalViewSplitters(); splitMainLayoutToLayouts(); } else { joinLayoutsToMainLayout(); root.destroyInternalViewSplitters(); } } else { if (panelUserSetAlignment===Latte.Types.Justify) { addInternalViewSplitters(); } else { root.destroyInternalViewSplitters(); } } updateIndexes(); } onLatteViewChanged: { if (latteView) { latteView.onXChanged.connect(visibilityManager.updateMaskArea); latteView.onYChanged.connect(visibilityManager.updateMaskArea); latteView.onWidthChanged.connect(visibilityManager.updateMaskArea); latteView.onHeightChanged.connect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.connect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.connect(visibilityManager.slotShowDockAfterLocationChange); latteView.visibility.onContainsMouseChanged.connect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.connect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.connect(visibilityManager.slotMustBeShown); updateContainsOnlyPlasmaTasks(); } } onDockContainsMouseChanged: { if (!dockContainsMouse) { initializeHoveredIndexes(); } } onDragEnter: { if (plasmoid.immutable || dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { event.ignore(); return; } if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0) { return; } if (latteApplet) { if (latteApplet.launchersDrop(event)) { root.addLaunchersMessage = true; if (root.addLaunchersInTaskManager) { return; } } else { var isSeparator = ( latteView.mimeContainsPlasmoid(event.mimeData, "audoban.applet.separator") || latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.separator") ); if (isSeparator && root.latteAppletContainer.containsPos(event)) { confirmedDragEntered = true dndSpacer.opacity = 0; dndSpacer.parent = root; return; } } } if (!confirmedDragEntered) { confirmedDragEntered = true; slotAnimationsNeedLength(1); } if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { LayoutManager.insertAtCoordinates2(dndSpacer, event.x, event.y) dndSpacer.opacity = 1; } } onDragMove: { if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") >= 0 || dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { return; } if (latteApplet) { if (latteApplet.launchersDrop(event)) { root.addLaunchersMessage = true; if (root.addLaunchersInTaskManager) { return; } } else { var isSeparator = ( latteView.mimeContainsPlasmoid(event.mimeData, "audoban.applet.separator") || latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.separator") ); if (isSeparator && root.latteAppletContainer.containsPos(event)) { confirmedDragEntered = true dndSpacer.opacity = 0; dndSpacer.parent = root; return; } } } if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { LayoutManager.insertAtCoordinates2(dndSpacer, event.x, event.y) dndSpacer.opacity = 1; } } onDragLeave: { if (confirmedDragEntered) { slotAnimationsNeedLength(-1); confirmedDragEntered = false; } root.addLaunchersMessage = false; dndSpacer.opacity = 0; dndSpacer.parent = root; } onDrop: { if (dockIsHidden || visibilityManager.inSlidingIn || visibilityManager.inSlidingOut) { return; } if (event.mimeData.formats.indexOf("application/x-orgkdeplasmataskmanager_taskbuttonitem") < 0) { if (latteApplet && latteApplet.launchersDrop(event) && root.addLaunchersInTaskManager) { latteApplet.launchersDropped(event.mimeData.urls); } else if (!latteApplet || (latteApplet && !latteView.mimeContainsPlasmoid(event.mimeData, "org.kde.latte.plasmoid"))) { plasmoid.processMimeData(event.mimeData, event.x, event.y); event.accept(event.proposedAction); } } if (confirmedDragEntered) { slotAnimationsNeedLength(-1); confirmedDragEntered = false; } root.addLaunchersMessage = false; dndSpacer.opacity = 0; //! this line is very important because it positions correctly the new applets //dndSpacer.parent = root; } onMaxLengthChanged: { layoutsContainer.updateSizeForAppletsInFill(); if (root.editMode) { updateAutomaticIconSize(); } } onToolBoxChanged: { if (toolBox) { toolBox.visible = false; } } property bool automaticSizeAnimation: false; onAutomaticIconSizeBasedSizeChanged: { if (!automaticSizeAnimation) { automaticSizeAnimation = true; slotAnimationsNeedBothAxis(1); } } onIconSizeChanged: { if (((iconSize === automaticIconSizeBasedSize) || (iconSize === root.maxIconSize)) && automaticSizeAnimation){ slotAnimationsNeedBothAxis(-1); automaticSizeAnimation=false; } } onIsReadyChanged: { if (isReady && !titleTooltipDialog.visible && titleTooltipDialog.activeItemHovered){ titleTooltipDialog.show(titleTooltipDialog.activeItem, titleTooltipDialog.activeItemText); } } onIsVerticalChanged: { if (isVertical) { if (plasmoid.configuration.panelPosition === Latte.Types.Left) plasmoid.configuration.panelPosition = Latte.Types.Top; else if (plasmoid.configuration.panelPosition === Latte.Types.Right) plasmoid.configuration.panelPosition = Latte.Types.Bottom; } else { if (plasmoid.configuration.panelPosition === Latte.Types.Top) plasmoid.configuration.panelPosition = Latte.Types.Left; else if (plasmoid.configuration.panelPosition === Latte.Types.Bottom) plasmoid.configuration.panelPosition = Latte.Types.Right; } } onProportionIconSizeChanged: { if (proportionIconSize!==-1) updateAutomaticIconSize(); } // onIconSizeChanged: console.log("Icon Size Changed:"+iconSize); Component.onCompleted: { // currentLayout.isLayoutHorizontal = isHorizontal LayoutManager.plasmoid = plasmoid; LayoutManager.root = root; LayoutManager.layout = layoutsContainer.mainLayout; LayoutManager.layoutS = layoutsContainer.startLayout; LayoutManager.layoutE = layoutsContainer.endLayout; LayoutManager.lastSpacer = lastSpacer; LayoutManager.restore(); plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; inStartupTimer.start(); } Component.onDestruction: { console.debug("Destroying Latte Dock Containment ui..."); if (latteView) { latteView.onXChanged.disconnect(visibilityManager.updateMaskArea); latteView.onYChanged.disconnect(visibilityManager.updateMaskArea); latteView.onWidthChanged.disconnect(visibilityManager.updateMaskArea); latteView.onHeightChanged.disconnect(visibilityManager.updateMaskArea); latteView.positioner.hideDockDuringLocationChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterLocationChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringScreenChangeStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterScreenChangeFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); latteView.positioner.hideDockDuringMovingToLayoutStarted.disconnect(visibilityManager.slotHideDockDuringLocationChange); latteView.positioner.showDockAfterMovingToLayoutFinished.disconnect(visibilityManager.slotShowDockAfterLocationChange); if (latteView.visibility) { latteView.visibility.onContainsMouseChanged.disconnect(visibilityManager.slotContainsMouseChanged); latteView.visibility.onMustBeHide.disconnect(visibilityManager.slotMustBeHide); latteView.visibility.onMustBeShown.disconnect(visibilityManager.slotMustBeShown); } } } Containment.onAppletAdded: { addApplet(applet, x, y); console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); } Containment.onAppletRemoved: { LayoutManager.removeApplet(applet); var flexibleFound = false; for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var applet = layoutsContainer.mainLayout.children[i].applet; if (applet && ((root.isHorizontal && applet.Layout.fillWidth) || (!root.isHorizontal && applet.Layout.fillHeight)) && applet.visible) { flexibleFound = true; break } } if (!flexibleFound) { lastSpacer.parent = layoutsContainer.mainLayout; } console.log(applet.pluginName); LayoutManager.save(); updateIndexes(); updateContainsOnlyPlasmaTasks(); } Plasmoid.onUserConfiguringChanged: { if (plasmoid.immutable) { if (dragOverlay) { dragOverlay.destroy(); } return; } // console.debug("user configuring", plasmoid.userConfiguring) if (plasmoid.userConfiguring) { latteView.setBlockHiding(true); // console.log("applets------"); for (var i = 0; i < plasmoid.applets.length; ++i) { // console.log("applet:"+i); plasmoid.applets[i].expanded = false; } if (!dragOverlay) { var component = Qt.createComponent("editmode/ConfigOverlay.qml"); if (component.status == Component.Ready) { dragOverlay = component.createObject(root); } else { console.log("Could not create ConfigOverlay"); console.log(component.errorString()); } component.destroy(); } else { dragOverlay.visible = true; } } else { latteView.setBlockHiding(false); if (latteView.visibility.isHidden) { latteView.visibility.mustBeShown(); } if (dragOverlay) { dragOverlay.visible = false; dragOverlay.destroy(); } } } Plasmoid.onImmutableChanged: { plasmoid.action("configure").visible = !plasmoid.immutable; plasmoid.action("configure").enabled = !plasmoid.immutable; ///Set Preferred Sizes/// ///Notice: they are set here because if they are set with a binding ///they break the !immutable experience, the latteView becomes too small ///to add applets /* if (plasmoid.immutable) { if(root.isHorizontal) { root.Layout.preferredWidth = (plasmoid.configuration.panelPosition === Latte.Types.Justify ? layoutsContainer.width + 0.5*iconMargin : layoutsContainer.mainLayout.width + iconMargin); } else { root.Layout.preferredHeight = (plasmoid.configuration.panelPosition === Latte.Types.Justify ? layoutsContainer.height + 0.5*iconMargin : layoutsContainer.mainLayout.height + iconMargin); } } else { if (root.isHorizontal) { root.Layout.preferredWidth = Screen.width; } else { root.Layout.preferredHeight = Screen.height; } }*/ visibilityManager.updateMaskArea(); } //////////////END OF CONNECTIONS //////////////START OF FUNCTIONS function addApplet(applet, x, y) { var container = appletContainerComponent.createObject(dndSpacer.parent) container.applet = applet; applet.parent = container.appletWrapper; applet.anchors.fill = container.appletWrapper; applet.visible = true; // don't show applet if it chooses to be hidden but still make it // accessible in the panelcontroller container.visible = Qt.binding(function() { return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && plasmoid.userConfiguring) }) addContainerInLayout(container, applet, x, y); updateContainsOnlyPlasmaTasks(); } function addContainerInLayout(container, applet, x, y){ // Is there a DND placeholder? Replace it! if ( (dndSpacer.parent === layoutsContainer.mainLayout) || (dndSpacer.parent === layoutsContainer.startLayout) || (dndSpacer.parent===layoutsContainer.endLayout)) { LayoutManager.insertBeforeForLayout(dndSpacer.parent, dndSpacer, container); dndSpacer.parent = root; return; // If the provided position is valid, use it. } else if (x >= 0 && y >= 0) { var index = LayoutManager.insertAtCoordinates2(container, x , y); // Fall through to determining an appropriate insert position. } else { var before = null; container.animationsEnabled = false; if (lastSpacer.parent === layoutsContainer.mainLayout) { before = lastSpacer; } // Insert icons to the left of whatever is at the center (usually a Task Manager), // if it exists. // FIXME TODO: This is a real-world fix to produce a sensible initial position for // launcher icons added by launcher menu applets. The basic approach has been used // since Plasma 1. However, "add launcher to X" is a generic-enough concept and // frequent-enough occurrence that we'd like to abstract it further in the future // and get rid of the ugliness of parties external to the containment adding applets // of a specific type, and the containment caring about the applet type. In a better // system the containment would be informed of requested launchers, and determine by // itself what it wants to do with that information. if (applet.pluginName == "org.kde.plasma.icon") { var middle = layoutsContainer.mainLayout.childAt(root.width / 2, root.height / 2); if (middle) { before = middle; } // Otherwise if lastSpacer is here, enqueue before it. } if (before) { LayoutManager.insertBefore(before, container); // Fall through to adding at the end. } else { container.parent = layoutsContainer.mainLayout; } } //Important, removes the first children of the layoutsContainer.mainLayout after the first //applet has been added lastSpacer.parent = root; updateIndexes(); } function addInternalViewSplitters(){ if (internalViewSplittersCount() === 0) { addInternalViewSplitter(plasmoid.configuration.splitterPosition); addInternalViewSplitter(plasmoid.configuration.splitterPosition2); } } function addInternalViewSplitter(pos){ var splittersCount = internalViewSplittersCount(); if(splittersCount<2){ var container = appletContainerComponent.createObject(root); container.internalSplitterId = splittersCount+1; container.visible = true; if(pos>=0 ){ LayoutManager.insertAtIndex(container, pos); } else { LayoutManager.insertAtIndex(container, Math.floor(layoutsContainer.mainLayout.count / 2)); } } } //! it is used in order to check the right click position //! the only way to take into account the visual appearance //! of the applet (including its spacers) function appletContainsPos(appletId, pos){ for (var i = 0; i < layoutsContainer.startLayout.children.length; ++i) { var child = layoutsContainer.startLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.mainLayout.children.length; ++i) { var child = layoutsContainer.mainLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } for (var i = 0; i < layoutsContainer.endLayout.children.length; ++i) { var child = layoutsContainer.endLayout.children[i]; if (child && child.applet && child.applet.id === appletId && child.containsPos(pos)) return true; } return false; } function checkLastSpacer() { lastSpacer.parent = root var expands = false; if (isHorizontal) { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillWidth) { expands = true; } } } else { for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if (item.Layout && item.Layout.fillHeight) { expands = true; } } } if (!expands) { lastSpacer.parent = layoutsContainer.mainLayout } } function clearZoom(){ if (latteApplet){ latteApplet.clearZoom(); } root.clearZoomSignal(); } function containmentActions(){ return latteView.containmentActions(); } function decimalToHex(d, padding) { var hex = Number(d).toString(16); padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding; while (hex.length < padding) { hex = "0" + hex; } return hex; } function disableDirectRender(){ // root.globalDirectRender = false; } function internalViewSplittersCount(){ var splitters = 0; for (var container in layoutsContainer.startLayout.children) { var item = layoutsContainer.startLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.mainLayout.children) { var item = layoutsContainer.mainLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } for (var container in layoutsContainer.endLayout.children) { var item = layoutsContainer.endLayout.children[container]; if(item && item.isInternalViewSplitter) { splitters = splitters + 1; } } return splitters; } function initializeHoveredIndexes() { layoutsContainer.hoveredIndex = -1; layoutsContainer.currentSpot = -1000; if (latteApplet) { latteApplet.initializeHoveredIndex(); } } function layoutManagerInsertBefore(place, item) { LayoutManager.insertBefore(place, item); } function layoutManagerInsertAfter(place, item) { LayoutManager.insertAfter(place, item); } function layoutManagerSave() { LayoutManager.save(); } function layoutManagerSaveOptions() { LayoutManager.saveOptions(); } function mouseInCanBeHoveredApplet(){ if (latteApplet && latteApplet.containsMouse()) return true; var applets = layoutsContainer.startLayout.children; for(var i=0; i=0; --i){ if(iconsArray[i] === size){ return true; } } return false; } function slotAnimationsNeedBothAxis(step) { if (step === 0) { return; } animationsNeedBothAxis = Math.max(animationsNeedBothAxis + step, 0); visibilityManager.updateMaskArea(); } function slotAnimationsNeedLength(step) { if (step === 0) { return; } animationsNeedLength = Math.max(animationsNeedLength + step, 0); //when need length animations are ended it would be a good idea //to update the tasks geometries in the plasmoid if(animationsNeedLength === 0 && latteApplet) { latteApplet.publishTasksGeometries(); } visibilityManager.updateMaskArea(); } function slotAnimationsNeedThickness(step) { if (step === 0) { return; } animationsNeedThickness = Math.max(animationsNeedThickness + step, 0); visibilityManager.updateMaskArea(); } //this is used when dragging a task in order to not hide the dock //and also by the menu appearing from tasks for the same reason function slotActionsBlockHiding(step) { //if (root.editMode) { // return; // } if ((step === 0) || (!latteView)) { return; } actionsBlockHiding = Math.max(actionsBlockHiding + step, 0); if (actionsBlockHiding > 0){ latteView.setBlockHiding(true); } else { if (!root.editMode) latteView.setBlockHiding(false); } } function slotPreviewsShown(){ if (latteView) { latteView.deactivateApplets(); } } function startCheckRestoreZoomTimer(){ checkRestoreZoom.start(); } function stopCheckRestoreZoomTimer(){ checkRestoreZoom.stop(); } function startDirectRenderDelayerDuringEntering(){ directRenderDelayerForEnteringTimer.start(); } function setGlobalDirectRender(value) { if (latteApplet && latteApplet.waitingLaunchers.length > 0) return; if (value === true) { if (mouseInCanBeHoveredApplet()) { root.globalDirectRender = true; } else { // console.log("direct render true ignored..."); } } else { root.globalDirectRender = false; } } function updateAutomaticIconSize() { if ( !blockAutomaticUpdateIconSize.running && !visibilityManager.inTempHiding && ((visibilityManager.normalState || root.editMode) && (root.autoDecreaseIconSize || (!root.autoDecreaseIconSize && root.iconSize!=root.maxIconSize))) && (iconSize===root.maxIconSize || iconSize === automaticIconSizeBasedSize) ) { blockAutomaticUpdateIconSize.start(); var layoutLength; var maxLength = root.maxLength; //console.log("------Entered check-----"); //console.log("max length: "+ maxLength); if (root.isVertical) { layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? layoutsContainer.startLayout.height+layoutsContainer.mainLayout.height+layoutsContainer.endLayout.height : layoutsContainer.mainLayout.height } else { layoutLength = (plasmoid.configuration.panelPosition === Latte.Types.Justify) ? layoutsContainer.startLayout.width+layoutsContainer.mainLayout.width+layoutsContainer.endLayout.width : layoutsContainer.mainLayout.width } var toShrinkLimit = maxLength-((root.zoomFactor-1)*(iconSize + thickMargins)); var toGrowLimit = maxLength-1.5*((root.zoomFactor-1)*(iconSize + thickMargins)); var newIconSizeFound = false; if (layoutLength > toShrinkLimit) { //must shrink // console.log("step3"); var nextIconSize = root.maxIconSize; do { nextIconSize = nextIconSize - iconStep; var factor = nextIconSize / iconSize; var nextLength = factor * layoutLength; } while ( (nextLength>toShrinkLimit) && (nextIconSize !== 16)); automaticIconSizeBasedSize = nextIconSize; newIconSizeFound = true; console.log("Step 3 - found:"+automaticIconSizeBasedSize); } else if ((layoutLength 0) { if (foundGoodSize === root.maxIconSize) { automaticIconSizeBasedSize = -1; } else { automaticIconSizeBasedSize = foundGoodSize; } newIconSizeFound = true // console.log("Step 4 - found:"+automaticIconSizeBasedSize); } else { // console.log("Step 4 - did not found..."); } } } } function updateContainsOnlyPlasmaTasks() { if (latteView) { root.containsOnlyPlasmaTasks = (latteView.tasksPresent() && !latteApplet); } else { root.containsOnlyPlasmaTasks = false; } } function updateSizeForAppletsInFill() { layoutsContainer.updateSizeForAppletsInFill(); } function splitMainLayoutToLayouts() { if (internalViewSplittersCount() === 2) { console.log("LAYOUTS: Moving applets from MAIN to THREE Layouts mode..."); var splitter = -1; var splitter2 = -1; var totalChildren = layoutsContainer.mainLayout.children.length; for (var i=0; i=0 && splitter2 === -1) { splitter2 = i; } } // console.log("update layouts 1:"+splitter + " - "+splitter2); for (var i=0; i<=splitter; ++i){ var item = layoutsContainer.mainLayout.children[0]; item.parent = layoutsContainer.startLayout; } splitter2 = splitter2 - splitter - 1; // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = layoutsContainer.mainLayout.children.length; for (var i=splitter2+1; i=0; --i) { var item1 = layoutsContainer.mainLayout.children[0]; item1.parent = layoutsContainer.startLayout; } var totalChildren2 = layoutsContainer.endLayout.children.length; for (var i=totalChildren2-1; i>=0; --i) { var item2 = layoutsContainer.endLayout.children[0]; item2.parent = layoutsContainer.startLayout; } var totalChildrenL = layoutsContainer.startLayout.children.length; for (var i=totalChildrenL-1; i>=0; --i) { var itemL = layoutsContainer.startLayout.children[0]; itemL.parent = layoutsContainer.mainLayout; } } //END functions ////BEGIN interfaces Connections { target: Latte.WindowSystem onCompositingActiveChanged: { visibilityManager.updateMaskArea(); } } Connections { target: latteView onWidthChanged:{ if (root.isHorizontal && proportionIconSize!==-1) updateAutomaticIconSize(); } onHeightChanged:{ if (root.isVertical && proportionIconSize!==-1) updateAutomaticIconSize(); } onContextMenuIsShownChanged: { if (!latteView.contextMenuIsShown) { checkRestoreZoom.start(); } else { root.setGlobalDirectRender(false); } } } Connections{ target: latteView && latteView.visibility ? latteView.visibility : root ignoreUnknownSignals : true onContainsMouseChanged: { if (mouseInHoverableArea()) { stopCheckRestoreZoomTimer(); } else { startCheckRestoreZoomTimer(); } } } Connections{ target: layoutsContainer onHoveredIndexChanged: { if (latteApplet && layoutsContainer.hoveredIndex>-1){ latteApplet.setHoveredIndex(-1); } if (latteApplet && latteApplet.windowPreviewIsShown && layoutsContainer.hoveredIndex>-1) { latteApplet.hidePreview(); } } } ////END interfaces /////BEGIN: Title Tooltip/////////// PlasmaCore.Dialog{ id: titleTooltipDialog type: PlasmaCore.Dialog.Tooltip flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.ToolTip location: plasmoid.location mainItem: RowLayout{ Layout.fillWidth: true Layout.fillHeight: true PlasmaComponents.Label{ id:titleLbl Layout.leftMargin: 4 Layout.rightMargin: 4 Layout.topMargin: 2 Layout.bottomMargin: 2 text: titleTooltipDialog.title } } visible: false property string title: "" property bool activeItemHovered: false property Item activeItem: null property Item activeItemTooltipParent: null property string activeItemText: "" Component.onCompleted: { root.clearZoomSignal.connect(titleTooltipDialog.hide); } Component.onDestruction: { root.clearZoomSignal.disconnect(titleTooltipDialog.hide); } function hide(debug){ if (!root.titleTooltips) return; activeItemHovered = false; hideTitleTooltipTimer.start(); } function show(taskItem, text){ if (!root.titleTooltips || (latteApplet && latteApplet.contextMenu)){ return; } activeItemHovered = true; if (activeItem !== taskItem) { activeItem = taskItem; activeItemTooltipParent = taskItem.tooltipVisualParent; activeItemText = text; } if (isReady) { showTitleTooltipTimer.start(); } } function update() { activeItemHovered = true title = activeItemText; visualParent = activeItemTooltipParent; if (latteApplet && latteApplet.windowPreviewIsShown) { latteApplet.hidePreview(); } visible = true; } } Timer { id: showTitleTooltipTimer interval: 100 onTriggered: { if (latteView && latteView.visibility && latteView.visibility.containsMouse) { titleTooltipDialog.update(); } if (titleTooltipDialog.visible) { titleTooltipCheckerToNotShowTimer.start(); } if (root.debugModeTimers) { console.log("containment timer: showTitleTooltipTimer called..."); } } } Timer { id: hideTitleTooltipTimer interval: 200 onTriggered: { if (!titleTooltipDialog.activeItemHovered) { titleTooltipDialog.visible = false; } if (root.debugModeTimers) { console.log("containment timer: hideTitleTooltipTimer called..."); } } } //! Timer to fix #811, rare cases that both a window preview and context menu are //! shown Timer { id: titleTooltipCheckerToNotShowTimer interval: 250 onTriggered: { if (titleTooltipDialog.visible && latteApplet && (latteApplet.contextMenu || latteApplet.windowPreviewIsShown)) { titleTooltipDialog.visible = false; } } } /////END: Title Tooltip/////////// ///////////////BEGIN components Component { id: appletContainerComponent Applet.AppletItem{} } ParabolicManager{ id: _parabolicManager } Indicators.Manager{ id: indicators } ///////////////END components PlasmaCore.ColorScope{ id: colorScopePalette } ///////////////BEGIN UI elements //it is used to check if the mouse is outside the layoutsContainer borders, //so in that case the onLeave event behavior should be trigerred RootMouseArea{ id: rootMouseArea } Loader{ active: root.debugModeWindow sourceComponent: DebugWindow{} } //! Load a sepia background in order to avoid black background Loader{ anchors.fill: parent active: !Latte.WindowSystem.compositingActive sourceComponent: Image{ anchors.fill: parent fillMode: Image.Tile source: root.hasUserSpecifiedBackground ? latteView.managedLayout.background : "../icons/wheatprint.jpg" } } EditMode.Visual{ id:editModeVisual // z: root.behaveAsPlasmaPanel ? 1 : 0 } Item{ id: panelBox anchors.fill:layoutsContainer // z: root.behaveAsPlasmaPanel ? 0 : 1 PanelBox{ id: panelBoxBackground } } Item { id: lastSpacer parent: layoutsContainer.mainLayout Layout.fillWidth: true Layout.fillHeight: true z:10 Rectangle{ anchors.fill: parent color: "transparent" border.color: "yellow" border.width: 1 } } Item { id: dndSpacer property int normalSize: root.iconSize + root.thickMargins - 1 width: normalSize height: normalSize Layout.preferredWidth: width Layout.preferredHeight: height opacity: 0 z:10 AddWidgetVisual{} } Loader{ anchors.fill: parent active: root.debugMode z:10 sourceComponent: Item{ Rectangle{ anchors.fill: parent color: "yellow" opacity: 0.30 } } } VisibilityManager{ id: visibilityManager } Layouts.Container { id: layoutsContainer } Colorizer.Manager { id: colorizerManager } ///////////////END UI elements ///////////////BEGIN TIMER elements //Timer to check if the mouse is still outside the latteView in order to restore zooms to 1.0 Timer{ id:checkRestoreZoom interval: 90 onTriggered: { if (latteApplet && (latteApplet.previewContainsMouse() || latteApplet.contextMenu)) return; if (latteView.contextMenuIsShown) return; if (!mouseInHoverableArea()) { setGlobalDirectRender(false); root.initializeHoveredIndexes(); root.clearZoom(); } if (root.debugModeTimers) { console.log("containment timer: checkRestoreZoom called..."); } } } //! Delayer in order to not activate directRendering when the mouse //! enters until the timer has ended. This way we make sure that the //! zoom-in animations will have ended. Timer{ id:directRenderDelayerForEnteringTimer interval: 3.2 * root.durationTime * units.shortDuration } //this is a delayer to update mask area, it is used in cases //that animations can not catch up with animations signals //e.g. the automaicIconSize case Timer{ id:delayUpdateMaskArea repeat:false; interval:300; onTriggered: { if (layoutsContainer.animationSent) { root.slotAnimationsNeedLength(-1); layoutsContainer.animationSent = false; } visibilityManager.updateMaskArea(); if (root.debugModeTimers) { console.log("containment timer: delayUpdateMaskArea called..."); } } } // This function is very costly! This timer makes sure that it can be called // only once every 1sec. Timer{ id:blockAutomaticUpdateIconSize interval: 1000 repeat: false onTriggered: root.updateAutomaticIconSize(); } //! It is used in order to slide-in the latteView on startup Timer{ id: inStartupTimer interval: 1500 repeat: false onTriggered: { if (inStartup) { visibilityManager.slotMustBeShown(); } } } ///////////////END TIMER elements } diff --git a/plasmoid/package/contents/ui/indicators/Manager.qml b/plasmoid/package/contents/ui/indicators/Manager.qml index 511b8cab..b499147b 100644 --- a/plasmoid/package/contents/ui/indicators/Manager.qml +++ b/plasmoid/package/contents/ui/indicators/Manager.qml @@ -1,58 +1,63 @@ /* * 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.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte 0.2 as Latte import "options" as IndicatorOptions import "styles" as IndicatorStyles import "../task/indicator" as TaskIndicator Item{ id: managerIndicator readonly property Item configuration: explicitOptions readonly property bool isEnabled: true readonly property bool reversed: plasmoid.configuration.reverseLinesPosition readonly property string type: "org.kde.latte.default" readonly property Component indicatorComponent: latteStyleIndicator readonly property Item info: Item{ readonly property bool needsIconColors: false + readonly property bool needsMouseEventCoordinates: false readonly property bool providesFrontLayer: false + readonly property bool providesHoveredAnimation: false + readonly property bool providesClickedAnimation: false readonly property int extraMaskThickness: 0 + readonly property real minThicknessPadding: 0 + readonly property real minLengthPadding:0 } IndicatorOptions.Latte { id : explicitOptions } //! Indicators Components Component { id: latteStyleIndicator IndicatorStyles.LatteIndicator{} } } diff --git a/plasmoid/package/contents/ui/task/IconItem.qml b/plasmoid/package/contents/ui/task/IconItem.qml index 00114f36..f125a462 100644 --- a/plasmoid/package/contents/ui/task/IconItem.qml +++ b/plasmoid/package/contents/ui/task/IconItem.qml @@ -1,731 +1,731 @@ /* * 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.4 import QtQuick.Layouts 1.1 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.plasma.private.taskmanager 0.1 as TaskManagerApplet import org.kde.kquickcontrolsaddons 2.0 as KQuickControlAddons import org.kde.latte 0.2 as Latte import "animations" as TaskAnimations //I am using KQuickControlAddons.QIconItem even though onExit it triggers the following error //QObject::~QObject: Timers cannot be stopped from another thread //but it increases performance almost to double during animation Item{ id: taskIcon width: wrapper.regulatorWidth height: wrapper.regulatorHeight //big interval to show shadows only after all the crappy adds and removes of tasks //have happened property bool firstDrawed: true property bool toBeDestroyed: false // three intervals in order to create the necessary buffers from the // PlasmaCore.IconItem, one big interval for the first creation of the // plasmoid, a second one for the first creation of a task and a small one // for simple updates. // This is done before especially on initialization stage some visuals // are not ready and empty buffers are created //property int firstDrawedInterval: root.initializationStep ? 2000 : 1000 // property int shadowInterval: firstDrawed ? firstDrawedInterval : 250 property int shadowInterval: firstDrawed ? 1000 : 250 property int shadowSize : root.appShadowSize readonly property bool smartLauncherEnabled: ((taskItem.isStartup === false) && (root.showInfoBadge || root.showProgressBadge)) readonly property variant iconDecoration: decoration readonly property color backgroundColor: iconImageBuffer.backgroundColor readonly property color glowColor: iconImageBuffer.glowColor property QtObject buffers: null property QtObject smartLauncherItem: null property Item titleTooltipVisualParent: titleTooltipParent property Item previewsTootipVisualParent: previewsTooltipParent /* Rectangle{ anchors.fill: parent border.width: 1 border.color: "green" color: "transparent" } */ onSmartLauncherEnabledChanged: { if (smartLauncherEnabled && !smartLauncherItem) { var smartLauncher = Qt.createQmlObject( " import org.kde.plasma.private.taskmanager 0.1 as TaskManagerApplet; TaskManagerApplet.SmartLauncherItem { }", taskIcon); smartLauncher.launcherUrl = Qt.binding(function() { return taskItem.launcherUrlWithIcon; }); smartLauncherItem = smartLauncher; } else if (!smartLauncherEnabled && smartLauncherItem) { smartLauncherItem.destroy(); smartLauncherItem = null; } } Rectangle{ id: draggedRectangle width: taskItem.isSeparator ? parent.width + 1 : iconImageBuffer.width+1 height: taskItem.isSeparator ? parent.height + 1 : iconImageBuffer.height+1 anchors.centerIn: iconGraphic opacity: 0 radius: 3 anchors.margins: 5 property color tempColor: theme.highlightColor color: tempColor border.width: 1 border.color: theme.highlightColor onTempColorChanged: tempColor.a = 0.35; } TitleTooltipParent{ id: titleTooltipParent thickness: root.zoomFactor * (root.iconSize + root.thickMargins) } TitleTooltipParent{ id: previewsTooltipParent thickness: root.zoomFactor * (root.iconSize + root.thickMargins) + 1 } // KQuickControlAddons.QIconItem{ Item{ id: iconGraphic width: parent.width height: parent.height //fix bug #478, when changing form factor sometimes the tasks are not positioned //correctly, in such case we make a fast reinitialization for the sizes Connections { target: plasmoid onFormFactorChanged:{ taskItem.inAddRemoveAnimation = false; wrapper.mScale = 1.01; wrapper.tempScaleWidth = 1.01; wrapper.tempScaleHeight = 1.01; wrapper.mScale = 1; wrapper.tempScaleWidth = 1; wrapper.tempScaleHeight = 1; } } Latte.IconItem{ id: iconImageBuffer anchors.centerIn: parent width: Math.round(newTempSize) //+ 2*taskIcon.shadowSize height: Math.round(width) source: decoration providesColors: indicators.info.needsIconColors opacity: root.enableShadows ? 0 : 1 visible: !taskItem.isSeparator && !badgesLoader.active //visible: !root.enableShadows onValidChanged: { if (!valid && (source === decoration || source === "unknown")) { source = "application-x-executable"; } } //! try to show the correct icon when a window is removed... libtaskmanager when a window is removed //! sends an unknown pixmap as icon Connections { target: taskItem onInRemoveStageChanged: { if (taskItem.inRemoveStage && iconImageBuffer.lastValidSourceName !== "") { iconImageBuffer.source = iconImageBuffer.lastValidSourceName; } } } property int zoomedSize: root.zoomFactor * root.iconSize property real basicScalingWidth : wrapper.inTempScaling ? (root.iconSize * wrapper.scaleWidth) : root.iconSize * wrapper.mScale property real basicScalingHeight : wrapper.inTempScaling ? (root.iconSize * wrapper.scaleHeight) : root.iconSize * wrapper.mScale property real newTempSize: { if (wrapper.opacity == 1) return Math.min(basicScalingWidth, basicScalingHeight) else return Math.max(basicScalingWidth, basicScalingHeight) } ///states for launcher animation states: [ State{ name: "*" when: !launcherAnimation.running && !newWindowAnimation.running && !taskItem.inAddRemoveAnimation && !fastRestoreAnimation.running AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.RightPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.LeftPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.TopPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.BottomPositioned ? parent.bottom : undefined; } }, State{ name: "inAddRemoveAnimation" when: taskItem.inAddRemoveAnimation AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.LeftPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.RightPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.BottomPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.TopPositioned ? parent.bottom : undefined; } }, State{ name: "animating" when: (launcherAnimation.running || newWindowAnimation.running || fastRestoreAnimation.running) && !taskItem.inAddRemoveAnimation AnchorChanges{ target:iconImageBuffer; anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined; anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined; anchors.right: root.position === PlasmaCore.Types.LeftPositioned ? parent.right : undefined; anchors.left: root.position === PlasmaCore.Types.RightPositioned ? parent.left : undefined; anchors.top: root.position === PlasmaCore.Types.BottomPositioned ? parent.top : undefined; anchors.bottom: root.position === PlasmaCore.Types.TopPositioned ? parent.bottom : undefined; } } ] ///transitions, basic for the anchor changes transitions: [ Transition{ from: "animating" to: "*" enabled: !fastRestoreAnimation.running && !taskItem.inMimicParabolicAnimation AnchorAnimation { duration: 1.5*root.durationTime*units.longDuration } } ] } //IconImageBuffer //! Shadows Loader{ id: taskWithShadow anchors.fill: iconImageBuffer active: root.enableShadows && !taskItem.isSeparator sourceComponent: DropShadow{ anchors.fill: parent color: root.appShadowColor fast: true samples: 2 * radius source: badgesLoader.active ? badgesLoader.item : iconImageBuffer radius: root.appShadowSize verticalOffset: 2 } } //! Shadows //! Combined Loader for Progress and Audio badges masks Loader{ id: badgesLoader anchors.fill: iconImageBuffer active: activateProgress > 0 asynchronous: true opacity: stateColorizer.opacity > 0 ? 0 : 1 property real activateProgress: showInfo || showProgress || showAudio ? 1 : 0 property bool showInfo: (root.showInfoBadge && taskIcon.smartLauncherItem && !taskItem.isSeparator && (taskIcon.smartLauncherItem.countVisible || taskItem.badgeIndicator > 0)) property bool showProgress: root.showProgressBadge && taskIcon.smartLauncherItem && !taskItem.isSeparator && taskIcon.smartLauncherItem.progressVisible property bool showAudio: (root.showAudioBadge && taskItem.hasAudioStream && taskItem.playingAudio && !taskItem.isSeparator) && !shortcutBadge.active Behavior on activateProgress { NumberAnimation { duration: root.durationTime*2*units.longDuration } } sourceComponent: Item{ ShaderEffect { id: iconOverlay enabled: false anchors.fill: parent property var source: ShaderEffectSource { sourceItem: Latte.IconItem{ width: iconImageBuffer.width height: iconImageBuffer.height source: iconImageBuffer.source } } property var mask: ShaderEffectSource { sourceItem: Item{ LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft && !root.vertical LayoutMirroring.childrenInherit: true width: iconImageBuffer.width height: iconImageBuffer.height Rectangle{ id: maskRect width: Math.max(badgeVisualsLoader.infoBadgeWidth, parent.width / 2) height: parent.height / 2 radius: parent.height visible: badgesLoader.showInfo || badgesLoader.showProgress //! Removes any remainings from the icon around the roundness at the corner Rectangle{ id: maskCorner width: parent.width/2 height: parent.height/2 } states: [ State { name: "default" when: (plasmoid.location !== PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } AnchorChanges { target: maskCorner anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } AnchorChanges { target: maskCorner anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } } ] } // progressMask Rectangle{ id: maskRect2 width: parent.width/2 height: width radius: width visible: badgesLoader.showAudio Rectangle{ id: maskCorner2 width:parent.width/2 height:parent.height/2 } states: [ State { name: "default" when: (plasmoid.location !== PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect2 anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } AnchorChanges { target: maskCorner2 anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined;} } }, State { name: "right" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: maskRect2 anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } AnchorChanges { target: maskCorner2 anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right;} } } ] } // audio mask } hideSource: true live: true } //end of mask supportsAtlasTextures: true fragmentShader: " varying highp vec2 qt_TexCoord0; uniform highp float qt_Opacity; uniform lowp sampler2D source; uniform lowp sampler2D mask; void main() { gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0 - (texture2D(mask, qt_TexCoord0.st).a)) * qt_Opacity; } " } //end of sourceComponent } } ////! //! START: Badges Visuals //! the badges visual get out from iconGraphic in order to be able to draw shadows that //! extend beyond the iconGraphic boundaries Loader { id: badgeVisualsLoader anchors.fill: iconImageBuffer active: badgesLoader.active readonly property int infoBadgeWidth: active ? publishedInfoBadgeWidth : 0 property int publishedInfoBadgeWidth: 0 sourceComponent: Item { ProgressOverlay{ id: infoBadge anchors.right: parent.right anchors.top: parent.top width: Math.max(parent.width, contentWidth) height: parent.height opacity: badgesLoader.activateProgress visible: badgesLoader.showInfo || badgesLoader.showProgress layer.enabled: root.enableShadows layer.effect: DropShadow { color: root.appShadowColor fast: true samples: 2 * radius source: infoBadge radius: root.appShadowSize verticalOffset: 2 } } AudioStream{ id: audioStreamBadge anchors.fill: parent opacity: badgesLoader.activateProgress visible: badgesLoader.showAudio layer.enabled: root.enableShadows layer.effect: DropShadow { color: root.appShadowColor fast: true samples: 2 * radius source: audioStreamBadge radius: root.appShadowSize verticalOffset: 2 } } Binding { target: badgeVisualsLoader property: "publishedInfoBadgeWidth" value: infoBadge.contentWidth } } } //! GREY-ing the information badges when the task is dragged //! moved out of badgeVisualsLoader in order to avoid crashes //! when the latte view is removed Loader { anchors.fill: iconImageBuffer active: badgeVisualsLoader.active sourceComponent: Colorize{ source: badgeVisualsLoader.item opacity: stateColorizer.opacity hue: stateColorizer.hue saturation: stateColorizer.saturation lightness: stateColorizer.lightness } } //! END: Badges Visuals //! Effects Colorize{ id: stateColorizer anchors.fill: iconImageBuffer source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: !isSeparator opacity:0 hue:0 saturation:0 lightness:0 } BrightnessContrast{ id:hoveredImage anchors.fill: iconImageBuffer source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: !isSeparator - opacity: taskItem.containsMouse && !clickedAnimation.running ? 1 : 0 + opacity: taskItem.containsMouse && !clickedAnimation.running && !indicators.info.providesHoveredAnimation ? 1 : 0 brightness: 0.30 contrast: 0.1 Behavior on opacity { NumberAnimation { duration: root.durationTime*units.longDuration } } } BrightnessContrast { id: brightnessTaskEffect anchors.fill: iconImageBuffer source: badgesLoader.active ? badgesLoader : iconImageBuffer visible: clickedAnimation.running && !isSeparator } //! Effects ShortcutBadge{ id: shortcutBadge } } VisualAddItem{ id: dropFilesVisual anchors.fill: iconGraphic visible: opacity == 0 ? false : true opacity: root.dropNewLauncher && !mouseHandler.onlyLaunchers && (root.dragSource == null) && (mouseHandler.hoveredItem === taskItem) ? 1 : 0 } Component.onDestruction: { taskIcon.toBeDestroyed = true; if(removingAnimation.removingItem) removingAnimation.removingItem.destroy(); } Connections{ target: taskItem onInAttentionChanged:{ if (!taskItem.inAttention && newWindowAnimation.running && taskItem.inAttentionAnimation) { newWindowAnimation.pause(); fastRestoreAnimation.start(); } } } ///// Animations ///// TaskAnimations.ClickedAnimation { id: clickedAnimation } TaskAnimations.LauncherAnimation { id:launcherAnimation } TaskAnimations.NewWindowAnimation { id: newWindowAnimation } TaskAnimations.RemoveWindowFromGroupAnimation { id: removingAnimation } TaskAnimations.FastRestoreAnimation { id: fastRestoreAnimation } //////////// States //////////////////// states: [ State{ name: "*" when: !taskItem.isDragged }, State{ name: "isDragged" when: ( (taskItem.isDragged) && (!root.editMode) ) } ] //////////// Transitions ////////////// transitions: [ Transition{ id: isDraggedTransition to: "isDragged" property int speed: root.durationTime*units.longDuration SequentialAnimation{ ScriptAction{ script: { icList.directRender = false; if(latteView) { latteView.globalDirectRender=false; } taskItem.inBlockingAnimation = true; root.clearZoom(); } } PropertyAnimation { target: wrapper property: "mScale" to: 1 + ((root.zoomFactor - 1) / 3) duration: isDraggedTransition.speed / 2 easing.type: Easing.OutQuad } ParallelAnimation{ PropertyAnimation { target: draggedRectangle property: "opacity" to: 1 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: iconImageBuffer property: "opacity" to: 0 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: stateColorizer property: "opacity" to: taskItem.isSeparator ? 0 : 1 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } } } onRunningChanged: { if(running){ taskItem.animationStarted(); //root.animations++; parabolicManager.clearTasksGreaterThan(index); parabolicManager.clearTasksLowerThan(index); if (latteView){ latteView.parabolicManager.clearAppletsGreaterThan(latteView.latteAppletPos); latteView.parabolicManager.clearAppletsLowerThan(latteView.latteAppletPos); } } } }, Transition{ id: defaultTransition from: "isDragged" to: "*" property int speed: root.durationTime*units.longDuration SequentialAnimation{ ScriptAction{ script: { icList.directRender = false; if(latteView) { latteView.globalDirectRender=false; } } } ParallelAnimation{ PropertyAnimation { target: draggedRectangle property: "opacity" to: 0 duration: defaultTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: iconImageBuffer property: "opacity" to: 1 duration: defaultTransition.speed easing.type: Easing.OutQuad } PropertyAnimation { target: stateColorizer property: "opacity" to: 0 duration: isDraggedTransition.speed easing.type: Easing.OutQuad } } /* PropertyAnimation { target: wrapper property: "mScale" to: 1; duration: isDraggedTransition.speed easing.type: Easing.OutQuad }*/ ScriptAction{ script: { taskItem.inBlockingAnimation = false; } } } onRunningChanged: { if(!running){ var halfZoom = 1 + ((root.zoomFactor - 1) / 2); wrapper.calculateScales((root.iconSize+root.thickMargins)/2); taskItem.animationEnded(); // root.animations--; } } } ] }// Icon Item diff --git a/plasmoid/package/contents/ui/task/animations/ClickedAnimation.qml b/plasmoid/package/contents/ui/task/animations/ClickedAnimation.qml index b7a3dcce..48d02430 100644 --- a/plasmoid/package/contents/ui/task/animations/ClickedAnimation.qml +++ b/plasmoid/package/contents/ui/task/animations/ClickedAnimation.qml @@ -1,83 +1,83 @@ /* * 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.0 import org.kde.plasma.plasmoid 2.0 ///////Activate animation///// SequentialAnimation{ id: clickedAnimation property bool pressed: taskItem.pressed property int speed: root.durationTime*units.longDuration property real maxMScale: Math.max(1,root.zoomFactor - (root.zoomFactor - 1) / 2) ParallelAnimation{ PropertyAnimation { target: brightnessTaskEffect property: "brightness" to: -0.5 duration: clickedAnimation.speed easing.type: Easing.OutQuad } /* PropertyAnimation { target: wrapper property: "mScale" to: root.taskInAnimation ? 1 : Math.max(clickedAnimation.maxMScale, wrapper.mScale - (root.zoomFactor - 1) / 2) duration: clickedAnimation.speed easing.type: Easing.OutQuad }*/ } ParallelAnimation{ PropertyAnimation { target: brightnessTaskEffect property: "brightness" to: 0 duration: clickedAnimation.speed easing.type: Easing.OutQuad } /* PropertyAnimation { target: wrapper property: "mScale" to: root.taskInAnimation ? 1 : root.zoomFactor duration: clickedAnimation.speed easing.type: Easing.OutQuad }*/ } onPressedChanged: { - if( !running && pressed&& + if(!running && pressed && !indicators.info.providesClickedAnimation && ((taskItem.lastButtonClicked == Qt.LeftButton)||(taskItem.lastButtonClicked == Qt.MidButton)) ){ //taskItem.animationStarted(); start(); } } onStopped: { if( !taskItem.isDragged){ //taskItem.animationEnded(); if(!root.latteView) checkListHovered.startDuration(6*units.longDuration); } } } diff --git a/plasmoid/package/contents/ui/task/indicator/LevelOptions.qml b/plasmoid/package/contents/ui/task/indicator/LevelOptions.qml index 31e4d5ee..fb570ae2 100644 --- a/plasmoid/package/contents/ui/task/indicator/LevelOptions.qml +++ b/plasmoid/package/contents/ui/task/indicator/LevelOptions.qml @@ -1,39 +1,41 @@ /* * 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.latte 0.2 as Latte Item { id: level + signal mousePressed(int x, int y); + property bool isBackground: true property bool isForeground: false property Item bridge onIsBackgroundChanged: { isForeground = !isBackground; } onIsForegroundChanged: { isBackground = !isForeground; } } diff --git a/plasmoid/package/contents/ui/task/indicator/Loader.qml b/plasmoid/package/contents/ui/task/indicator/Loader.qml index cc0781f1..addf09be 100644 --- a/plasmoid/package/contents/ui/task/indicator/Loader.qml +++ b/plasmoid/package/contents/ui/task/indicator/Loader.qml @@ -1,62 +1,73 @@ /* * 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.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte 0.2 as Latte Loader { id: indicatorLoader anchors.bottom: (root.position === PlasmaCore.Types.BottomPositioned) ? parent.bottom : undefined anchors.top: (root.position === PlasmaCore.Types.TopPositioned) ? parent.top : undefined anchors.left: (root.position === PlasmaCore.Types.LeftPositioned) ? parent.left : undefined anchors.right: (root.position === PlasmaCore.Types.RightPositioned) ? parent.right : undefined anchors.horizontalCenter: !root.vertical ? parent.horizontalCenter : undefined anchors.verticalCenter: root.vertical ? parent.verticalCenter : undefined active: level.bridge && level.bridge.active && (level.isBackground || (level.isForeground && indicators.info.providesFrontLayer)) sourceComponent: indicators.indicatorComponent width: { if (locked) { return visualLockedWidth; } return !root.vertical ? taskItem.wrapperAlias.width - 2*taskItem.wrapperAlias.mScale*root.lengthExtMargin : taskItem.wrapperAlias.width; } height: { if (locked) { return visualLockedHeight; } return root.vertical ? taskItem.wrapperAlias.height - 2*taskItem.wrapperAlias.mScale*root.lengthExtMargin : taskItem.wrapperAlias.height; } readonly property bool locked: inAttentionAnimation || inNewWindowAnimation property real visualLockedWidth: root.iconSize + root.internalWidthMargins property real visualLockedHeight: root.iconSize + root.internalHeightMargins + //! Connections !// + property Item level + + Connections { + target: taskItem + enabled: indicators.info.needsMouseEventCoordinates + onPressed: { + var fixedPos = indicatorLoader.mapFromItem(taskItem, mouse.x, mouse.y); + level.mousePressed(Math.round(fixedPos.x), Math.round(fixedPos.y)); + } + } }