/**************************************************************************** Copyright 2012,2015 by Sebastian KΓΌgler <sebas@kde.org> ** Copyright 2015 by Kai Uwe Broulik <kde@privat.broulik.de> ** ** This program 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. ** ** This program 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, write to the ** Free Software Foundation, Inc., ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . ****************************************************************************/import QtQuick 2.0import org.kde.plasma.core 2.0 as PlasmaCoreimport org.kde.plasma.components 2.0 as PlasmaComponentsimport org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddonsimport org.kde.plasma.plasmoid 2.0Item {id: toolBoxButtonproperty string text: main.Plasmoid.activityNameproperty bool isCorner: !buttonMouse.dragging &&((state == "topleft") || (state == "topright") ||(state == "bottomright") || (state == "bottomleft"))property bool isHorizontal: (state != "left" && state != "right")rotation: switch(state) {case "left":return -90;case "right":return 90;default:return 0;}transform: Translate {x: state == "left" ? Math.round(-width/2 + height/2) : state == "right" ? + Math.round(width/2 - height/2) : 0Behavior on x {NumberAnimation {duration: units.shortDuration * 3;easing.type: Easing.InOutExpo;}}}transformOrigin: Item.CenterBehavior on rotation {NumberAnimation {duration: units.shortDuration * 3;easing.type: Easing.InOutExpo;}enabled: visible}Behavior on x {NumberAnimation {duration: units.shortDuration * 3;easing.type: Easing.InOutExpo;}enabled: visible}Behavior on y {NumberAnimation {duration: units.shortDuration * 3;easing.type: Easing.InOutExpo;}enabled: visible}width: buttonLayout.width + (buttonLayout.width % 2)height: buttonLayout.height + (buttonLayout.height % 2)//x and y default to 0, so top left would be correct//If the position is anything else it will updated via onXChanged during intialisationstate: "topleft"onXChanged: stateTimer.restart()onYChanged: stateTimer.restart()Timer {id: stateTimerinterval: 100onTriggered: updateState()}function updateState() {var container = main;//print(" w: " + container.width +"x"+container.height+" : "+x+"/"+y+" tbw: " + toolBoxButton.width);var x = toolBoxButton.x - main.x;var y = toolBoxButton.y - main.y;var cornerSnap = iconWidthif (x < cornerSnap && y < cornerSnap) {toolBoxButton.state = "topleft";} else if (container.width - x - buttonLayout.width < cornerSnap && y < cornerSnap) {toolBoxButton.state = "topright";} else if (container.width - x - buttonLayout.width < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) {toolBoxButton.state = "bottomright";} else if (x < cornerSnap && container.height - y - buttonLayout.width < cornerSnap) {toolBoxButton.state = "bottomleft";//top diagonal half} else if (x > (y * (container.width/container.height))) {//Top edgeif (container.width - x > y ) {toolBoxButton.state = "top";//right edge} else {//toolBoxButton.transformOrigin = Item.BottomRighttoolBoxButton.state = "right";}//bottom diagonal half} else {//Left edgeif (container.height - y > x ) {//toolBoxButton.transformOrigin = Item.TopLefttoolBoxButton.state = "left";//Bottom edge} else {toolBoxButton.state = "bottom";}}if (!buttonMouse.pressed) {main.placeToolBox(toolBoxButton.state);}}PlasmaCore.FrameSvgItem {id: backgroundFrameimagePath: isCorner ? "widgets/translucentbackground" : "widgets/background"opacity: buttonMouse.containsMouse ? 1.0 : 0.4x: -margins.lefty: -margins.topwidth: (isCorner ? buttonLayout.height : buttonLayout.width) + margins.left + margins.rightheight: buttonLayout.height + margins.top + margins.bottomBehavior on width {NumberAnimation {duration: units.longDuration;easing.type: Easing.InOutQuad;}}Behavior on opacity {NumberAnimation {duration: units.longDuration;}}}Row {id: buttonLayout//when in the corner centre in the middle of the remaining space//the visible space is the width of the background frame + one margin, the other is offscreen//we want to work out the offset which is the visible frame width - our icon width / 2//X is relative to the start of button, but the frame is one marging wider to the left so this needs taking into accountx: isCorner ? Math.round((parent.width - width) / 2 + units.smallSpacing) : 0spacing: units.smallSpacingBehavior on x {NumberAnimation {duration: units.longDuration;easing.type: Easing.InOutQuad;}}PlasmaCore.SvgItem {id: toolBoxIconsvg: PlasmaCore.Svg {id: iconSvgimagePath: "widgets/configuration-icons"onRepaintNeeded: toolBoxIcon.elementId = iconSvg.hasElement("menu") ? "menu" : "configure"}elementId: iconSvg.hasElement("menu") ? "menu" : "configure"anchors.verticalCenter: parent.verticalCenterwidth: iconSizeheight: iconSizeopacity: buttonMouse.containsMouse || (toolBoxLoader.item && toolBoxLoader.item.visible) ? 1 : 0.5rotation: isHorizontal ? 0 : -90;transformOrigin: Item.CenterBehavior on opacity {NumberAnimation {duration: units.longDuration;easing.type: Easing.InOutExpo;}}}PlasmaComponents.Label {id: activityNameopacity: isCorner ? 0 : 1text: toolBoxButton.textBehavior on opacity {//only have this animation when going from hidden -> shownenabled: activityName.opacity == 0SequentialAnimation {//pause to allow the toolbox frame to resize//otherwise we see the text overflow the box//whilst that animatesPauseAnimation {duration: units.longDuration}NumberAnimation {duration: units.shortDurationeasing.type: Easing.InOutExpo}}}}}MouseArea {id: buttonMouseproperty QtObject container: mainproperty int pressedXproperty int pressedYproperty bool dragging: falseanchors {fill: parentmargins: -10}drag {target: main.Plasmoid.immutable ? undefined : toolBoxButtonminimumX: 0maximumX: container.width - toolBoxIcon.widthminimumY: 0maximumY: container.height - toolBoxIcon.height}hoverEnabled: trueonPressed: {pressedX = toolBoxButton.xpressedY = toolBoxButton.y}onPositionChanged: {if (pressed && (Math.abs(toolBoxButton.x - pressedX) > iconSize ||Math.abs(toolBoxButton.y - pressedY) > iconSize)) {dragging = true;}}onClicked: {plasmoid.contextualActionsAboutToShow();toolBoxLoader.active = true// the dialog auto-closes on losing focustoolBoxLoader.item.visible = !main.dialogWasVisibleplasmoid.focus = true;}onReleased: {main.Plasmoid.configuration.ToolBoxButtonState = toolBoxButton.state;main.Plasmoid.configuration.ToolBoxButtonX = toolBoxButton.x;main.Plasmoid.configuration.ToolBoxButtonY = toolBoxButton.y;//print("Saved coordinates for ToolBox in config: " + toolBoxButton.x + ", " +toolBoxButton.x);if (dragging) {main.placeToolBox();}dragging = false;stateTimer.stop();updateState();}onCanceled: dragging = false;}states: [State {name: "topleft"},State {name: "top"},State {name: "topright"},State {name: "right"},State {name: "bottomright"},State {name: "bottom"},State {name: "bottomleft"},State {name: "topleft"},State {name: "left"}]}