diff --git a/containments/desktop/package/contents/ui/AppletAppearance.qml b/containments/desktop/package/contents/ui/AppletAppearance.qml index 80f410276..7537a22ca 100644 --- a/containments/desktop/package/contents/ui/AppletAppearance.qml +++ b/containments/desktop/package/contents/ui/AppletAppearance.qml @@ -1,626 +1,735 @@ /* * Copyright 2011-2013 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2014 David Edmundson * Copyright 2015 Eike Hein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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.0 import QtQuick.Layouts 1.1 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 as KQuickControlsAddons import org.kde.plasma.plasmoid 2.0 Item { id: appletItem property int handleWidth: iconSize property int minimumHandleHeight: 7 * (root.iconSize + 7) + margins.top + margins.bottom property int handleHeight: (height < minimumHandleHeight) ? minimumHandleHeight : height property string category property bool showAppletHandle: temporaryShowAppletHandle || plasmoid.editMode property bool temporaryShowAppletHandle: false property real controlsOpacity: (plasmoid.immutable || !showAppletHandle) ? 0 : 1 property string backgroundHints: "NoBackground" property bool hasBackground: false property bool handleMerged: (height > minimumHandleHeight && !appletHandle.forceFloating) property bool animationsEnabled: false property bool floating: true // turns off layoutManagment space handling for appletItem property alias innerEndHeight: mouseListener.endHeight property alias innerEndWidth: mouseListener.endWidth property alias innerHeight: mouseListener.height property alias innerWidth: mouseListener.width property int minimumWidth: Math.max(root.layoutManager.cellSize.width, appletContainer.minimumWidth + margins.left + margins.right); property int minimumHeight: Math.max(root.layoutManager.cellSize.height, appletContainer.minimumHeight + margins.top + margins.bottom); property int maximumWidth: appletContainer.maximumWidth + margins.left + margins.right; property int maximumHeight: appletContainer.maximumHeight + margins.top + margins.bottom; property alias applet: appletContainer.applet property Item contents: appletContainer property alias margins: plasmoidBackground.margins property alias imagePath: plasmoidBackground.imagePath visible: false QtObject { id: d property real lastX: 0 property real lastY: 0 } onMinimumWidthChanged: { if (width < minimumWidth) { releasePosition(); width = minimumWidth; positionItem(); if (showAppletHandle && !handleMerged) appletHandle.positionHandle(); } } onMinimumHeightChanged: { if (height < minimumHeight) { releasePosition(); height = minimumHeight; positionItem(); if (showAppletHandle && !handleMerged) appletHandle.positionHandle(); } } onMaximumWidthChanged: { if (width > maximumWidth) { releasePosition(); width = maximumWidth; positionItem(); if (showAppletHandle && !handleMerged) appletHandle.positionHandle(); } } onMaximumHeightChanged: { if (height > maximumHeight) { releasePosition(); height = maximumHeight; positionItem(); if (showAppletHandle && !handleMerged) appletHandle.positionHandle(); } } onHeightChanged: { if (height > maximumHeight) innerEndHeight = maximumHeight; else if (height < minimumHeight) innerEndHeight = minimumHeight; else innerEndHeight = height; } onWidthChanged: { if (width > maximumWidth) innerEndWidth = maximumWidth; else if (width < minimumWidth) innerEndWidth = minimumWidth; else innerEndWidth = width; } onXChanged: { if (animationsEnabled) { animationsEnabled = false; mouseListener.x += d.lastX - x; animationsEnabled = true; } mouseListener.x = mouseListener.endX = (width - innerEndWidth)/2; d.lastX = x; } onYChanged: { if (animationsEnabled) { animationsEnabled = false; mouseListener.y += d.lastY - y; animationsEnabled = true; } mouseListener.y = mouseListener.endY = (height - innerEndHeight)/2; d.lastY = y; } // use this function to position appletItem instead of root.layoutManager.positionItem(appletItem) function positionItem() { if (floating) return; root.layoutManager.positionItem(appletItem); root.layoutManager.saveItem(appletItem); } // use this function to free appletItem position instead of // root.layoutManager.setSpaceAvailable(appletItem.x, appletItem.y, appletItem.width, appletItem.height, true) function releasePosition() { if (!floating) root.layoutManager.setSpaceAvailable(x, y, width, height, true); } function updateBackgroundHints() { hasBackground = (applet.backgroundHints != "NoBackground"); if (applet.backgroundHints == 1) { appletItem.imagePath = "widgets/background"; backgroundHints = "StandardBackground"; } else if (applet.backgroundHints == 2) { appletItem.imagePath = "widgets/translucentbackground" backgroundHints = "TranslucentBackground"; } else if (applet.backgroundHints == 0) { appletItem.imagePath = "" backgroundHints = "NoBackground"; } else { backgroundHints = "DefaultBackground"; appletItem.imagePath = "widgets/background"; } //print("Backgroundhints changed: " + appletItem.imagePath); } KQuickControlsAddons.MouseEventListener { id: mouseListener // used as inner applet (which would not be sized over or under size limits ) // centered in appletItem.onXChanged and onYChanged due to allow animations on X and Y property int pressX: -1 property int pressY: -1 // for animations property int endHeight: minimumHeight property int endWidth: minimumWidth property int endX: 0 property int endY: 0 function startDrag(mouse) { dragMouseArea.dragging = true; eventGenerator.sendGrabEventRecursive(appletItem, KQuickControlsAddons.EventGenerator.UngrabMouse); eventGenerator.sendGrabEvent(dragMouseArea, KQuickControlsAddons.EventGenerator.GrabMouse); eventGenerator.sendMouseEvent(dragMouseArea, KQuickControlsAddons.EventGenerator.MouseButtonPress, mouse.x, mouse.y, Qt.LeftButton, Qt.LeftButton, 0); } height: endHeight width: endWidth z: 10 hoverEnabled: true onPressed: { if (!plasmoid.immutable && mouse.modifiers == Qt.AltModifier) { if (!dragMouseArea.dragging) { startDrag(mouse) } return; } pressX = mouse.x; pressY = mouse.y; } onPressAndHold: { if (!plasmoid.immutable && plasmoid.configuration.pressToMove) { if (!dragMouseArea.dragging && !root.isDrag(pressX, pressY, mouse.x, mouse.y)) { temporaryShowAppletHandle = true; startDrag(mouse) } } pressX = -1; pressY = -1; } onContainsMouseChanged: { animationsEnabled = true; if (!plasmoid.immutable && (!plasmoid.configuration.pressToMove || !containsMouse)) { hoverTracker.restart(); } } Timer { id: hoverTracker repeat: false interval: root.handleDelay onTriggered: { if (mouseListener.containsMouse || (appletHandle.item && (appletHandle.item.containsMouse || appletHandle.item.pressed))) { if (!plasmoid.configuration.pressToMove) { temporaryShowAppletHandle = true; } } else if (!dragMouseArea.dragging) { temporaryShowAppletHandle = false; } } } Item { anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } width: parent.width+handleWidth; z: mouseListener.z + 4 PlasmaCore.FrameSvgItem { id: plasmoidBackground visible: backgroundHints != PlasmaCore.Types.NoBackground imagePath: "widgets/background" anchors { left: parent.left; top: parent.top; bottom: parent.bottom; } width: parent.width - _handleWidth smooth: true property real _handleWidth: (showAppletHandle && handleMerged) ? 0 : handleWidth Behavior on _handleWidth { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } } Connections { target: plasmoid onImmutableChanged: { // print(" TB dragMouseArea.visible: " + plasmoid.immutable) dragMouseArea.visible = !plasmoid.immutable; temporaryShowAppletHandle = false; } onAppletRemoved: { // print("Applet removed Applet-" + applet.id) if (applet.id == appletItem.applet.id) { // print("Destroying Applet-" + applet.id) root.layoutManager.saveRotation(appletItem); appletItem.releasePosition(); //applet.action("remove").trigger(); //appletItem.destroy() appletItem.destroy(); } } } Connections { target: applet onBackgroundHintsChanged: { // print("plasmoid.backgroundHintsChanged"); updateBackgroundHints(); } } MouseArea { id: dragMouseArea anchors.fill: parent z: appletContainer.z - 2 visible: !plasmoid.immutable property int zoffset: 1000 drag.target: appletItem property bool dragging: false // Set by mouseListener.onPressAndHold -- drag.active only becomes true on movement. function endDrag() { appletItem.z = appletItem.z - zoffset; repositionTimer.running = false; placeHolderPaint.opacity = 0; animationsEnabled = true; appletItem.floating = false; appletItem.positionItem(); root.layoutManager.save(); dragging = false; } onDraggingChanged: { cursorShape = dragging ? Qt.DragMoveCursor : Qt.ArrowCursor; } onPressed: { appletItem.z = appletItem.z + zoffset; animationsEnabled = false; mouse.accepted = true; appletItem.releasePosition(); appletItem.floating = true; placeHolder.syncWithItem(appletItem); placeHolderPaint.opacity = root.haloOpacity; } onPositionChanged: { var pos = mapToItem(root.parent, mouse.x, mouse.y); var newCont = plasmoid.containmentAt(pos.x, pos.y); if (newCont && newCont != plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, pos.x, pos.y); newCont.addApplet(appletItem.applet, newPos.x, newPos.y); placeHolderPaint.opacity = 0; } else { placeHolder.syncWithItem(appletItem); } } onCanceled: { endDrag(); appletHandle.positionHandle(); } onReleased: { endDrag(); appletHandle.positionHandle(); } } Item { id: appletContainer anchors { fill: parent leftMargin: plasmoidBackground.margins.left rightMargin: plasmoidBackground.margins.right + handleWidth topMargin: plasmoidBackground.margins.top bottomMargin: plasmoidBackground.margins.bottom } z: mouseListener.z+1 property QtObject applet readonly property int maxInt: 1000000 // dirty hack to convert js number to qml int property var minimumSize: { var size; if (applet && applet.Layout) { var layout = applet.Layout size = { 'width': layout.minimumWidth, 'height': layout.minimumHeight }; } else { size = { 'width': 0, 'height': 0 }; } return size; } property var maximumSize: { var size; if (applet && applet.Layout) { var layout = applet.Layout size = { 'width': layout.maximumWidth, 'height': layout.maximumHeight }; } else { size = { 'width': Number.POSITIVE_INFINITY, 'height': Number.POSITIVE_INFINITY }; } if (size.width > maxInt) size.width = maxInt; if (size.height > maxInt) size.height = maxInt; return size; } onMinimumSizeChanged: { minimumHeight = minimumSize.height if (minimumHeight > maximumSize.height) maximumHeight = minimumHeight else if (maximumHeight !== maximumSize.height) maximumHeight = maximumSize.height minimumWidth = minimumSize.width if (minimumWidth > maximumSize.width) maximumWidth = minimumWidth else if (maximumWidth !== maximumSize.width) maximumWidth = maximumSize.width } onMaximumSizeChanged: { maximumHeight = maximumSize.height if (maximumHeight < minimumSize.height) minimumHeight = maximumHeight else if (minimumHeight !== minimumSize.height) minimumHeight = minimumSize.height maximumWidth = maximumSize.width if (maximumWidth < minimumSize.width) minimumWidth = maximumWidth else if (minimumWidth !== minimumSize.width) minimumWidth = minimumSize.width } property int minimumWidth: 0 property int minimumHeight: 0 property int maximumWidth: maxInt property int maximumHeight: maxInt function appletDestroyed() { // print("Applet DESTROYED."); appletItem.releasePosition(); applet.action("remove").trigger(); appletItem.destroy() } onAppletChanged: { if (!applet) { return; } applet.parent = appletContainer; applet.anchors.fill = appletContainer; updateBackgroundHints(); } Connections { target: appletHandle.item onRemoveApplet: { killAnim.running = true; } } Behavior on opacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } SequentialAnimation { id: killAnim PlasmaExtras.DisappearAnimation { targetItem: appletItem } ScriptAction { script: { appletItem.scale = 1; appletContainer.appletDestroyed(); } } } Loader { id: busyLoader anchors.centerIn: parent z: appletContainer.z + 1 active: applet && applet.busy source: "BusyOverlay.qml" asynchronous: true } Component.onCompleted: PlasmaExtras.AppearAnimation { targetItem: appletItem } } Loader { id: appletHandle z: appletContainer.z + 1 property bool forceFloating : false anchors { verticalCenter: parent.verticalCenter right: plasmoidBackground.right } Connections { target: appletItem onShowAppletHandleChanged: { if (appletItem.showAppletHandle) { appletItem.z += dragMouseArea.zoffset; appletHandle.positionHandle(); if (appletHandle.source == "") { appletHandle.source = "AppletHandle.qml"; } } else { appletItem.z -= dragMouseArea.zoffset; } } onHandleMergedChanged: { if (appletItem.handleMerged) { appletHandle.anchors.verticalCenterOffset = 0; } else { appletHandle.positionHandle(); } } } Connections { target: appletHandle.item onMoveFinished: { appletHandle.positionHandle(); } } function positionHandle() { // Don't show handle outside of desktop var available = plasmoid.availableScreenRect; var x = Math.min(Math.max(0, appletItem.x + mouseListener.endX), available.width - appletItem.width + mouseListener.endX); var y = Math.min(Math.max(0, appletItem.y + mouseListener.endY), available.height - appletItem.height + mouseListener.endY); var verticalCenter = (y + mouseListener.endHeight / 2); var topOutside = (verticalCenter - minimumHandleHeight / 2); var bottomOutside = verticalCenter + minimumHandleHeight / 2 - available.height; if (bottomOutside > 0) { anchors.verticalCenterOffset = -bottomOutside; } else if (topOutside < 0) { anchors.verticalCenterOffset = -topOutside; } else { anchors.verticalCenterOffset = 0; } var rightOutside = x + mouseListener.endWidth + handleWidth - available.width; appletHandle.anchors.rightMargin = appletItem.margins.right + Math.max(0, rightOutside); appletHandle.forceFloating = rightOutside > 0; } } } Behavior on x { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on y { enabled: animationsEnabled NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on width { enabled: animationsEnabled NumberAnimation { id: widthAnimation duration: units.longDuration easing.type: Easing.InOutQuad } } Behavior on height { enabled: animationsEnabled NumberAnimation { id: heightAnimation duration: units.longDuration easing.type: Easing.InOutQuad } } } Behavior on controlsOpacity { NumberAnimation { duration: units.longDuration easing.type: Easing.InOutQuad } } + //sides + ResizeHandle { + anchors { + left: parent.left + top: parent.top + right: parent.right + leftMargin: units.gridUnit + rightMargin: units.gridUnit + } + cursorShape: Qt.SizeVerCursor + moveX: false + moveY: true + resizeWidth: false + resizeHeight: true + } + ResizeHandle { + anchors { + left: parent.left + bottom: parent.bottom + right: parent.right + leftMargin: units.gridUnit + rightMargin: units.gridUnit + } + cursorShape: Qt.SizeVerCursor + moveX: false + moveY: false + resizeWidth: false + resizeHeight: true + } + ResizeHandle { + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + topMargin: units.gridUnit + bottomMargin: units.gridUnit + } + enabled: !parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeHorCursor + moveX: true + moveY: false + resizeWidth: true + resizeHeight: false + } + ResizeHandle { + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + topMargin: units.gridUnit + bottomMargin: units.gridUnit + } + enabled: parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeHorCursor + moveX: false + moveY: false + resizeWidth: true + resizeHeight: false + } + //corners + ResizeHandle { + anchors { + left: parent.left + top: parent.top + } + enabled: !parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeFDiagCursor + moveX: true + moveY: true + resizeWidth: true + resizeHeight: true + } + ResizeHandle { + anchors { + right: parent.right + top: parent.top + } + enabled: parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeBDiagCursor + moveX: false + moveY: true + resizeWidth: true + resizeHeight: true + } + ResizeHandle { + anchors { + left: parent.left + bottom: parent.bottom + } + enabled: !parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeBDiagCursor + moveX: true + moveY: false + resizeWidth: true + resizeHeight: true + } + ResizeHandle { + anchors { + right: parent.right + bottom: parent.bottom + } + enabled: parent.LayoutMirroring.enabled || !showAppletHandle + cursorShape: Qt.SizeFDiagCursor + moveX: false + moveY: false + resizeWidth: true + resizeHeight: true + } + Component.onCompleted: { floating = false; layoutTimer.running = true layoutTimer.restart() visible = false } } diff --git a/containments/desktop/package/contents/ui/AppletHandle.qml b/containments/desktop/package/contents/ui/AppletHandle.qml index 7f5080a69..682d185bc 100644 --- a/containments/desktop/package/contents/ui/AppletHandle.qml +++ b/containments/desktop/package/contents/ui/AppletHandle.qml @@ -1,340 +1,309 @@ /* * Copyright 2011-2013 Sebastian Kügler * Copyright 2011 Marco Martin * Copyright 2014 David Edmundson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public License for more details * * You should have received a copy of the GNU Library 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.0 import QtQuick.Layouts 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons import org.kde.plasma.components 2.0 as PlasmaComponents KQuickControlsAddons.MouseEventListener { id: appletHandle opacity: appletItem.controlsOpacity visible: opacity > 0 width: appletItem.handleWidth height: Math.max(appletItem.innerHeight - appletItem.margins.top - appletItem.margins.bottom, buttonColumn.implicitHeight) hoverEnabled: true onContainsMouseChanged: { if (!containsMouse && !pressed) { hoverTracker.restart() } } onReleased: { if (!containsMouse) { hoverTracker.restart() } } //z: dragMouseArea.z + 1 property int buttonMargin: 6 property int minimumHeight: 6 * (root.iconSize + buttonMargin) signal removeApplet signal moveFinished transform: Translate { x: (handleMerged ? 0 : controlsOpacity * appletHandle.width) * (appletHandle.LayoutMirroring.enabled ? -1 : 1) } PlasmaCore.FrameSvgItem { id: noBackgroundHandle visible: controlsOpacity > 0 z: plasmoidBackground.z - 10 anchors { top: parent.top bottom: parent.bottom left: parent.left right: parent.right // verticalCenter: parent.verticalCenter leftMargin: -margins.left topMargin: -margins.top rightMargin: -margins.right bottomMargin: -margins.bottom } smooth: true imagePath: (backgroundHints == "NoBackground" || !handleMerged) ? "widgets/background" : "" } PlasmaComponents.Label { id: toolTipDelegate width: contentWidth height: contentHeight property Item toolTip text: (toolTip != null) ? toolTip.mainText : "" } ColumnLayout { id: buttonColumn width: appletItem.handleWidth anchors { top: parent.top bottom: parent.bottom right: parent.right } spacing: buttonMargin*2 ActionButton { svg: configIconsSvg elementId: "size-diagonal-tr2bl" iconSize: root.iconSize mainText: i18n("Resize") active: !resizeHandle.pressed - MouseArea { + ResizeHandle { id: resizeHandle anchors { fill: parent margins: -buttonMargin } - - property int startX - property int startY - - onPressed: { - parent.hideToolTip(); - mouse.accepted = true - animationsEnabled = false; - startX = mouse.x; - startY = mouse.y; - appletItem.releasePosition(); - appletItem.floating = true; - appletContainer.clip = true - } - onPositionChanged: { - var xDelta = startX - mouse.x; - var yDelta = startY - mouse.y; - - if (LayoutMirroring.enabled) { - var oldRight = appletItem.x + appletItem.width; - appletItem.width = Math.min(Math.max(appletItem.minimumWidth, appletItem.width + xDelta), appletItem.maximumWidth); - appletItem.x = oldRight - appletItem.width; - } else { - appletItem.width = Math.min(Math.max(appletItem.minimumWidth, appletItem.width - xDelta), appletItem.maximumWidth); - } - - var oldBottom = appletItem.y + appletItem.height; - appletItem.height = Math.min(Math.max(appletItem.minimumHeight, appletItem.height + yDelta), appletItem.maximumHeight); - appletItem.y = oldBottom - appletItem.height; - } - onReleased: { - animationsEnabled = true - appletItem.floating = false; - appletItem.positionItem(); - root.layoutManager.save() - appletContainer.clip = false - } + onPressed: parent.hideToolTip(); + cursorShape: parent.LayoutMirroring.enabled ? Qt.SizeFDiagCursor : Qt.SizeBDiagCursor + moveX: parent.LayoutMirroring.enabled + moveY: true + resizeWidth: true + resizeHeight: true } } ActionButton { id: rotateButton svg: configIconsSvg elementId: "rotate" mainText: i18n("Rotate") iconSize: root.iconSize action: (applet) ? applet.action("rotate") : null active: !rotateHandle.pressed Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } MouseArea { id: rotateHandle anchors { fill: parent margins: -buttonMargin } property int startRotation property real startCenterRelativeAngle; function pointAngle(pos) { var r = Math.sqrt(pos.x * pos.x + pos.y * pos.y); var cosine = pos.x / r; if (pos.y >= 0) { return Math.acos(cosine) * (180/Math.PI); } else { return -Math.acos(cosine) * (180/Math.PI); } } function centerRelativePos(x, y) { var mousePos = appletItem.parent.mapFromItem(rotateButton, x, y); var centerPos = appletItem.parent.mapFromItem(appletItem, appletItem.width/2, appletItem.height/2); mousePos.x -= centerPos.x; mousePos.y -= centerPos.y; return mousePos; } onPressed: { parent.hideToolTip(); mouse.accepted = true animationsEnabled = false; startRotation = appletItem.rotation; startCenterRelativeAngle = pointAngle(centerRelativePos(mouse.x, mouse.y)); } onPositionChanged: { var rot = startRotation%360; var snap = 4; var newRotation = Math.round(pointAngle(centerRelativePos(mouse.x, mouse.y)) - startCenterRelativeAngle + startRotation); if (newRotation < 0) { newRotation = newRotation + 360; } else if (newRotation >= 360) { newRotation = newRotation % 360; } snapIt(0); snapIt(90); snapIt(180); snapIt(270); function snapIt(snapTo) { if (newRotation > (snapTo - snap) && newRotation < (snapTo + snap)) { newRotation = snapTo; } } //print("Start: " + startRotation + " new: " + newRotation); appletItem.rotation = newRotation; } onReleased: { // save rotation // print("saving..."); root.layoutManager.saveItem(appletItem); } } } ActionButton { svg: configIconsSvg elementId: "configure" iconSize: root.iconSize visible: (action && typeof(action) != "undefined") ? action.enabled : false action: (applet) ? applet.action("configure") : null Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } } ActionButton { svg: configIconsSvg elementId: "maximize" iconSize: root.iconSize visible: (action && typeof(action) != "undefined") ? action.enabled : false action: (applet) ? applet.action("run associated application") : null Component.onCompleted: { if (action && typeof(action) != "undefined") { action.enabled = true } } } //spacer MouseArea { id: dragMouseArea implicitHeight: root.iconSize * 2 Layout.fillWidth: true Layout.fillHeight: true property int zoffset: 1000 drag.target: appletItem cursorShape: Qt.DragMoveCursor onPressed: { appletItem.z = appletItem.z + zoffset; animationsEnabled = false mouse.accepted = true appletItem.releasePosition(); appletItem.floating = true; placeHolder.syncWithItem(appletItem) placeHolderPaint.opacity = root.haloOpacity; } onPositionChanged: { var pos = mapToItem(root.parent, mouse.x, mouse.y); var newCont = plasmoid.containmentAt(pos.x, pos.y); if (newCont && newCont != plasmoid) { var newPos = newCont.mapFromApplet(plasmoid, pos.x, pos.y); newCont.addApplet(appletItem.applet, newPos.x, newPos.y); placeHolderPaint.opacity = 0; } else { placeHolder.syncWithItem(appletItem); } } onReleased: { appletItem.z = appletItem.z - zoffset; repositionTimer.running = false placeHolderPaint.opacity = 0 animationsEnabled = true appletItem.floating = false; appletItem.positionItem(); root.layoutManager.save() appletHandle.moveFinished() } } Item { Layout.minimumWidth: closeButton.width Layout.minimumHeight: closeButton.height ActionButton { id: closeButton svg: configIconsSvg elementId: "close" mainText: i18n("Remove") iconSize: root.iconSize visible: { if (!applet) { return false; } var a = applet.action("remove"); return (a && typeof(a) != "undefined") ? a.enabled : false; } // we don't set action, since we want to catch the button click, // animate, and then trigger the "remove" action // Triggering the action is handled in the appletItem, we just // emit a signal here to avoid the applet-gets-removed-before-we- // can-animate it race condition. onClicked: { appletHandle.removeApplet(); } Component.onCompleted: { var a = applet.action("remove"); if (a && typeof(a) != "undefined") { a.enabled = true } } } } } } diff --git a/containments/desktop/package/contents/ui/ResizeHandle.qml b/containments/desktop/package/contents/ui/ResizeHandle.qml new file mode 100644 index 000000000..cadc8b492 --- /dev/null +++ b/containments/desktop/package/contents/ui/ResizeHandle.qml @@ -0,0 +1,94 @@ +/* + * Copyright 2011-2013 Sebastian Kügler + * Copyright 2011 Marco Martin + * Copyright 2014 David Edmundson + * Copyright 2015 Eike Hein + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library 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.0 +import QtQuick.Layouts 1.1 +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 as KQuickControlsAddons +import org.kde.plasma.plasmoid 2.0 + + +MouseArea { + width: units.gridUnit + height: units.gridUnit + cursorShape: Qt.SizeVerCursor + z: 99999 + + //to controls the resize/move behavior + property bool moveX + property bool moveY + property bool resizeWidth + property bool resizeHeight + + //internal + property int startX + property int startY + property int startWidth + property int startHeight + + + visible: applet.backgroundHints != PlasmaCore.Types.NoBackground && enabled && !plasmoid.immutable + LayoutMirroring.enabled: false + onPressed: { + mouse.accepted = true + animationsEnabled = false; + var pos = mapToItem(root, mouse.x, mouse.y); + startX = pos.x; + startY = pos.y; + startWidth = appletItem.width; + startHeight = appletItem.height; + appletItem.releasePosition(); + appletItem.floating = true; + appletContainer.clip = true + } + onPositionChanged: { + var pos = mapToItem(root, mouse.x, mouse.y); + var xDelta = moveX ? pos.x - startX : startX - pos.x; + var yDelta = moveY ? startY - pos.y : pos.y - startY; + + var oldRight = appletItem.x + appletItem.width; + if (resizeWidth) { + appletItem.width = Math.min(Math.max(appletItem.minimumWidth, startWidth - xDelta), appletItem.maximumWidth); + } + + var oldBottom = appletItem.y + appletItem.height; + if (resizeHeight) { + appletItem.height = Math.min(Math.max(appletItem.minimumHeight, startHeight + yDelta), appletItem.maximumHeight); + } + + if (moveX) { + appletItem.x = oldRight - appletItem.width; + } + if (moveY) { + appletItem.y = oldBottom - appletItem.height; + } + } + onReleased: { + animationsEnabled = true + appletItem.floating = false; + appletItem.positionItem(); + root.layoutManager.save() + appletContainer.clip = false + } +}