You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
latte-dock/containment/package/contents/ui/editmode/ConfigOverlay.qml

653 lines
23 KiB
QML

/*
* Copyright 2016 Smith AR <audoban@openmailbox.org>
* Michail Vourlakos <mvourlakos@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.7
import QtQuick.Layouts 1.0
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.kquickcontrolsaddons 2.0
import org.kde.latte.core 0.2 as LatteCore
MouseArea {
id: configurationArea
z: 1000
width: plasmoid.formFactor === PlasmaCore.Types.Horizontal ? root.width : thickness
height: plasmoid.formFactor === PlasmaCore.Types.Vertical ? root.height : thickness
visible: root.inConfigureAppletsMode
hoverEnabled: root.inConfigureAppletsMode
focus: true
cursorShape: {
if (currentApplet && tooltip.visible && currentApplet.latteStyleApplet) {
return root.isHorizontal ? Qt.SizeHorCursor : Qt.SizeVerCursor;
}
return Qt.ArrowCursor;
}
property bool isResizingLeft: false
property bool isResizingRight: false
property Item currentApplet
property Item previousCurrentApplet
property Item currentHoveredLayout: {
if (placeHolder.parent !== configurationArea) {
return placeHolder.parent;
}
return currentApplet ? currentApplet.parent : null
}
property int lastX
property int lastY
property int appletX
property int appletY
readonly property int thickness: metrics.mask.thickness.maxNormal - metrics.extraThicknessForNormal
readonly property int spacerHandleSize: units.smallSpacing
onHeightChanged: tooltip.visible = false;
onWidthChanged: tooltip.visible = false;
function hoveredItem(x, y) {
//! main layout
var relevantLayout;
var item;
if (!item) {
// main layout
relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0);
item = layoutsContainer.mainLayout.childAt(x-relevantLayout.x, y-relevantLayout.y);
}
if (!item) {
// start layout
relevantLayout = mapFromItem(layoutsContainer.startLayout,0,0);
item = layoutsContainer.startLayout.childAt(x-relevantLayout.x, y-relevantLayout.y);
}
if (!item) {
// end layout
relevantLayout = mapFromItem(layoutsContainer.endLayout,0,0);
item = layoutsContainer.endLayout.childAt(x-relevantLayout.x, y-relevantLayout.y);
}
return item;
}
function relevantLayoutForApplet(curapplet) {
var relevantLayout;
if (curapplet.parent === layoutsContainer.mainLayout) {
relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0);
} else if (curapplet.parent === layoutsContainer.startLayout) {
relevantLayout = mapFromItem(layoutsContainer.startLayout, 0, 0);
} else if (curapplet.parent === layoutsContainer.endLayout) {
relevantLayout = mapFromItem(layoutsContainer.endLayout, 0, 0);
}
return relevantLayout;
}
onPositionChanged: {
if (pressed) {
//! is this really needed ????
/*var padding = units.gridUnit * 3;
if (currentApplet && (mouse.x < -padding || mouse.y < -padding ||
mouse.x > width + padding || mouse.y > height + padding)) {
var newCont = plasmoid.containmentAt(mouse.x, mouse.y);
if (newCont && newCont != plasmoid) {
var newPos = newCont.mapFromApplet(plasmoid, mouse.x, mouse.y);
newCont.addApplet(currentApplet.applet, newPos.x, newPos.y);
root.dragOverlay.currentApplet = null;
return;
}
}*/
if(currentApplet){
if (plasmoid.formFactor === PlasmaCore.Types.Vertical) {
currentApplet.y += (mouse.y - lastY);
// handle.y = currentApplet.y;
} else {
currentApplet.x += (mouse.x - lastX);
// handle.x = currentApplet.x;
}
}
lastX = mouse.x;
lastY = mouse.y;
var mousesink = {x: mouse.x, y: mouse.y};
//! ignore thicknes moving at all cases
if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) {
mousesink.y = 0;
} else {
mousesink.x = 0;
}
var item = hoveredItem(mousesink.x, mousesink.y);
if (item && item !== placeHolder) {
placeHolder.parent = configurationArea;
var posInItem = mapToItem(item, mousesink.x, mousesink.y);
if ((plasmoid.formFactor === PlasmaCore.Types.Vertical && posInItem.y < item.height/2) ||
(plasmoid.formFactor !== PlasmaCore.Types.Vertical && posInItem.x < item.width/2)) {
root.layoutManagerInsertBefore(item, placeHolder);
} else {
root.layoutManagerInsertAfter(item, placeHolder);
}
}
} else {
var item = hoveredItem(mouse.x, mouse.y);
if (root.dragOverlay && item && item !== lastSpacer) {
root.dragOverlay.currentApplet = item;
} else {
currentApplet = null;
root.dragOverlay.currentApplet = null;
}
}
if (root.dragOverlay.currentApplet) {
hideTimer.stop();
tooltip.visible = true;
tooltip.raise();
}
}
onExited: hideTimer.restart();
onCurrentAppletChanged: {
previousCurrentApplet = currentApplet;
if (!currentApplet || !root.dragOverlay.currentApplet) {
hideTimer.restart();
return;
}
var relevantLayout = relevantLayoutForApplet(currentApplet) ;
if (!relevantLayout) {
return;
}
handle.x = relevantLayout.x + currentApplet.x;
handle.y = relevantLayout.y + currentApplet.y;
handle.width = currentApplet.width;
handle.height = currentApplet.height;
lockButton.checked = currentApplet.lockZoom;
colorizingButton.checked = !currentApplet.userBlocksColorizing;
repositionHandler.restart();
}
onPressed: {
if (!root.dragOverlay.currentApplet) {
return;
}
root.layouter.appletsInParentChange = true;
var relevantApplet = mapFromItem(currentApplet, 0, 0);
var rootArea = mapFromItem(root, 0, 0);
appletX = mouse.x - relevantApplet.x + rootArea.x;
appletY = mouse.y - relevantApplet.y + rootArea.y;
lastX = mouse.x;
lastY = mouse.y;
placeHolder.width = currentApplet.width;
placeHolder.height = currentApplet.height;
handle.width = currentApplet.width;
handle.height = currentApplet.height;
root.layoutManagerInsertBefore(currentApplet, placeHolder);
currentApplet.parent = root;
currentApplet.x = root.isHorizontal ? lastX - currentApplet.width/2 : lastX-appletX;
currentApplet.y = root.isVertical ? lastY - currentApplet.height/2 : lastY-appletY;
currentApplet.z = 900;
}
onReleased: {
if (!handle.visible) {
tooltip.visible = false;
}
if (!root.dragOverlay.currentApplet) {
return;
}
if(currentApplet && currentApplet.applet){
if (plasmoid.formFactor === PlasmaCore.Types.Vertical) {
currentApplet.applet.configuration.length = handle.height;
} else {
currentApplet.applet.configuration.length = handle.width;
}
}
configurationArea.isResizingLeft = false;
configurationArea.isResizingRight = false;
root.layoutManagerInsertBefore(placeHolder, currentApplet);
placeHolder.parent = configurationArea;
currentApplet.z = 1;
var relevantLayout = mapFromItem(layoutsContainer.mainLayout, 0, 0);
handle.x = relevantLayout.x + currentApplet.x;
handle.y = relevantLayout.y + currentApplet.y;
// handle.width = currentApplet.width;
// handle.height = currentApplet.height;
root.layoutManagerSave();
if (root.myView.alignment === LatteCore.Types.Justify) {
root.moveAppletsBasedOnJustifyAlignment();
}
root.layouter.appletsInParentChange = false;
layouter.updateSizeForAppletsInFill();
}
onWheel: {
if (!currentApplet || !currentApplet.latteStyleApplet) {
return;
}
var angle = wheel.angleDelta.y / 8;
if (angle > 12)
currentApplet.latteStyleApplet.increaseLength();
else if (angle < 12)
currentApplet.latteStyleApplet.decreaseLength();
}
Connections {
target: currentApplet
onWidthChanged: {
if (configurationArea.pressed && root.isHorizontal) {
currentApplet.x = configurationArea.lastX - currentApplet.width/2;
}
}
onHeightChanged: {
if (configurationArea.pressed && root.isVertical) {
currentApplet.y = configurationArea.lastY - currentApplet.height/2;
}
}
}
Item {
id: placeHolder
visible: configurationArea.pressed
Layout.fillWidth: currentApplet ? currentApplet.Layout.fillWidth : false
Layout.fillHeight: currentApplet ? currentApplet.Layout.fillHeight : false
readonly property bool isPlaceHolder: true
}
Binding {
target: placeHolder
property: "width"
when: currentApplet
value: currentApplet ? currentApplet.width : 0
}
Binding {
target: placeHolder
property: "width"
when: currentApplet
value: currentApplet ? currentApplet.height : 0
}
//Because of the animations for the applets the handler can not catch up to
//reposition itself when the currentApplet position or size changes.
//This timer fixes that situation
Timer {
id: repositionHandler
interval: 100
onTriggered: handle.updatePlacement();
}
Timer {
id: hideTimer
interval: animations.duration.large * 2
onTriggered: {
if (!tooltipMouseArea.containsMouse) {
tooltip.visible = false;
currentApplet = null;
}
}
}
Connections {
target: currentApplet
onXChanged: handle.updatePlacement();
onYChanged: handle.updatePlacement();
onWidthChanged: handle.updatePlacement();
onHeightChanged: handle.updatePlacement()
}
Item {
id: handle
visible: currentApplet && (configurationArea.containsMouse || tooltipMouseArea.containsMouse)
Loader {
anchors.fill: parent
active: root.debug.graphicsEnabled
sourceComponent: Rectangle {
color: "transparent"
border.width:1
border.color: "yellow"
}
}
//BEGIN functions
function updatePlacement(){
if(currentApplet){
var transformChoords = configurationArea.mapFromItem(currentApplet, 0, 0)
if (handle.x !== transformChoords.x
|| handle.y !== transformChoords.y
|| handle.width !== currentApplet.width
|| handle.height !== currentApplet.height) {
handle.x = transformChoords.x;
handle.y = transformChoords.y;
handle.width = currentApplet.width;
handle.height = currentApplet.height;
repositionHandler.restart();
}
}
}
//END functions
Item {
id: handleVisualItem
width: root.isHorizontal ? parent.width : thickness
height: root.isHorizontal ? thickness : parent.height
readonly property int thickness: root.isHorizontal ? parent.height - metrics.margin.screenEdge : parent.width - metrics.margin.screenEdge
Rectangle{
anchors.fill: parent
color: theme.backgroundColor
radius: 3
opacity: 0.35
}
PlasmaCore.IconItem {
source: "transform-move"
width: Math.min(144, parent.width, parent.height)
height: width
anchors.centerIn: parent
opacity: 0.9
layer.enabled: graphicsSystem.isAccelerated
layer.effect: DropShadow {
radius: root.myView.itemShadow.size
fast: true
samples: 2 * radius
color: root.myView.itemShadow.shadowColor
verticalOffset: 2
}
}
states:[
State{
name: "bottom"
when: plasmoid.location === PlasmaCore.Types.BottomEdge
AnchorChanges{
target: handleVisualItem;
anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined;
anchors.right: undefined; anchors.left: undefined; anchors.top: undefined; anchors.bottom: parent.bottom;
}
PropertyChanges{
target: handleVisualItem;
anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: metrics.margin.screenEdge;
anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0;
}
},
State{
name: "top"
when: plasmoid.location === PlasmaCore.Types.TopEdge
AnchorChanges{
target: handleVisualItem;
anchors.horizontalCenter: parent.horizontalCenter; anchors.verticalCenter: undefined;
anchors.right: undefined; anchors.left: undefined; anchors.top: parent.top; anchors.bottom: undefined;
}
PropertyChanges{
target: handleVisualItem;
anchors.leftMargin: 0; anchors.rightMargin: 0; anchors.topMargin: metrics.margin.screenEdge; anchors.bottomMargin: 0;
anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0;
}
},
State{
name: "left"
when: plasmoid.location === PlasmaCore.Types.LeftEdge
AnchorChanges{
target: handleVisualItem;
anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter;
anchors.right: undefined; anchors.left: parent.left; anchors.top: undefined; anchors.bottom: undefined;
}
PropertyChanges{
target: handleVisualItem;
anchors.leftMargin: metrics.margin.screenEdge; anchors.rightMargin: 0; anchors.topMargin:0; anchors.bottomMargin: 0;
anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0;
}
},
State{
name: "right"
when: plasmoid.location === PlasmaCore.Types.RightEdge
AnchorChanges{
target: handleVisualItem;
anchors.horizontalCenter: undefined; anchors.verticalCenter: parent.verticalCenter;
anchors.right: parent.right; anchors.left: undefined; anchors.top: undefined; anchors.bottom: undefined;
}
PropertyChanges{
target: handleVisualItem;
anchors.leftMargin: 0; anchors.rightMargin: metrics.margin.screenEdge; anchors.topMargin:0; anchors.bottomMargin: 0;
anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0;
}
}
]
}
Behavior on opacity {
NumberAnimation {
duration: animations.duration.large
easing.type: Easing.InOutQuad
}
}
}
PlasmaCore.Dialog {
id: tooltip
visualParent: currentApplet
type: PlasmaCore.Dialog.Dock
flags: Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus | Qt.BypassWindowManagerHint | Qt.ToolTip
location: plasmoid.location
onVisualParentChanged: {
if (visualParent && currentApplet
&& (currentApplet.applet || currentApplet.isSeparator || currentApplet.isInternalViewSplitter)) {
configureButton.visible = !currentApplet.isInternalViewSplitter && (currentApplet.applet.pluginName !== root.plasmoidName)
&& currentApplet.applet.action("configure") && currentApplet.applet.action("configure").enabled;
closeButton.visible = !currentApplet.isInternalViewSplitter && currentApplet.applet.action("remove") && currentApplet.applet.action("remove").enabled;
lockButton.visible = !currentApplet.isInternalViewSplitter
&& (currentApplet.applet.pluginName !== root.plasmoidName)
&& !currentApplet.isSeparator;
colorizingButton.visible = root.colorizerEnabled && !currentApplet.appletBlocksColorizing && !currentApplet.isInternalViewSplitter;
label.text = currentApplet.isInternalViewSplitter ? i18n("Justify Splitter") : currentApplet.applet.title;
}
}
mainItem: MouseArea {
id: tooltipMouseArea
enabled: currentApplet
width: handleRow.childrenRect.width + (2 * handleRow.spacing)
height: Math.max(configureButton.height, label.contentHeight, closeButton.height)
hoverEnabled: true
LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft
LayoutMirroring.childrenInherit: true
onEntered: hideTimer.stop();
onExited: hideTimer.restart();
Row {
id: handleRow
anchors.horizontalCenter: parent.horizontalCenter
spacing: 2*units.smallSpacing
Row{
spacing: units.smallSpacing
PlasmaComponents.ToolButton {
id: configureButton
anchors.verticalCenter: parent.verticalCenter
iconSource: "configure"
tooltip: i18n("Configure applet")
onClicked: {
tooltip.visible = false;
currentApplet.applet.action("configure").trigger();
}
}
PlasmaComponents.Label {
id: label
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: units.smallSpacing
textFormat: Text.PlainText
maximumLineCount: 1
}
Row{
spacing: units.smallSpacing/2
PlasmaComponents.ToolButton{
id: colorizingButton
checkable: true
iconSource: "color-picker"
tooltip: i18n("Enable painting for this applet")
onCheckedChanged: {
currentApplet.userBlocksColorizing = !checked;
root.layoutManagerSaveOptions();
}
}
PlasmaComponents.ToolButton{
id: lockButton
checkable: true
iconSource: checked ? "lock" : "unlock"
tooltip: i18n("Disable parabolic effect for this applet")
onCheckedChanged: {
currentApplet.lockZoom = checked;
root.layoutManagerSaveOptions();
}
}
PlasmaComponents.ToolButton {
id: closeButton
anchors.verticalCenter: parent.verticalCenter
iconSource: "delete"
tooltip: i18n("Remove applet")
onClicked: {
tooltip.visible = false;
if(currentApplet && currentApplet.applet)
currentApplet.applet.action("remove").trigger();
}
}
}
}
}
}
}
states: [
State {
name: "bottom"
when: (plasmoid.location === PlasmaCore.Types.BottomEdge)
AnchorChanges {
target: configurationArea
anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined;
horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
},
State {
name: "top"
when: (plasmoid.location === PlasmaCore.Types.TopEdge)
AnchorChanges {
target: configurationArea
anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined;
horizontalCenter:parent.horizontalCenter; verticalCenter:undefined}
}
},
State {
name: "left"
when: (plasmoid.location === PlasmaCore.Types.LeftEdge)
AnchorChanges {
target: configurationArea
anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined;
horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
},
State {
name: "right"
when: (plasmoid.location === PlasmaCore.Types.RightEdge)
AnchorChanges {
target: configurationArea
anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right;
horizontalCenter:undefined; verticalCenter:parent.verticalCenter}
}
}
]
}