3
0
mirror of https://github.com/Qortal/Brooklyn.git synced 2025-02-23 23:55:54 +00:00
Scare Crowe d2ebfd0519 QortalOS Titan 5.60.12
Screw the description like that inbred T3Q
2022-03-05 21:17:59 +05:00

535 lines
22 KiB
QML

/*
SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.1
import QtQuick.Layouts 1.1
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.draganddrop 2.0 as DragDrop
import "LayoutManager.js" as LayoutManager
DragDrop.DropArea {
id: root
width: 640
height: 48
//BEGIN properties
Layout.minimumWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.minimumWidth + (isHorizontal && toolBox ? toolBox.width : 0))
Layout.maximumWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.maximumWidth + (isHorizontal && toolBox ? toolBox.width : 0))
Layout.preferredWidth: fixedWidth > 0 ? fixedWidth : (currentLayout.Layout.preferredWidth + (isHorizontal && toolBox ? toolBox.width : 0))
Layout.minimumHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.minimumHeight + (!isHorizontal && toolBox ? toolBox.height : 0))
Layout.maximumHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.maximumHeight + (!isHorizontal && toolBox ? toolBox.height : 0))
Layout.preferredHeight: fixedHeight > 0 ? fixedHeight : (currentLayout.Layout.preferredHeight + (!isHorizontal && toolBox? toolBox.height : 0))
property Item toolBox
property var layoutManager: LayoutManager
property Item dragOverlay
property bool isHorizontal: plasmoid.formFactor !== PlasmaCore.Types.Vertical
property int fixedWidth: 0
property int fixedHeight: 0
// These are invisible and only used to read panel margins
// Both will fallback to "standard" panel margins if the theme does not
// define a normal or a thick margin.
PlasmaCore.FrameSvgItem {
id: panelSvg
visible: false
prefix: 'normal'
imagePath: "widgets/panel-background"
}
PlasmaCore.FrameSvgItem {
id: thickPanelSvg
visible: false
prefix: 'thick'
imagePath: "widgets/panel-background"
}
property bool marginAreasEnabled: panelSvg.margins != thickPanelSvg.margins
property var marginHighlightSvg: PlasmaCore.Svg{imagePath: "widgets/margins-highlight"}
//Margins are either the size of the margins in the SVG, unless that prevents the panel from being at least half a smallMedium icon) tall at which point we set the margin to whatever allows it to be that...or if it still won't fit, 1.
//the size a margin should be to force a panel to be the required size above
readonly property real spacingAtMinSize: Math.round(Math.max(1, (currentLayout.isLayoutHorizontal ? root.height : root.width) - units.iconSizes.smallMedium)/2)
//END properties
//BEGIN functions
function addApplet(applet, x, y) {
// don't show applet if it chooses to be hidden but still make it
// accessible in the panelcontroller
// Due to the nature of how "visible" propagates in QML, we need to
// explicitly set it on the container (so the Layout ignores it)
// as well as the applet (so it reliably knows about), otherwise it can
// happen that an applet erroneously thinks it's visible, or suddenly
// starts thinking that way on teardown (virtual desktop pager)
// leading to crashes
var visibleBinding = Qt.binding(function() {
return applet.status !== PlasmaCore.Types.HiddenStatus || (!plasmoid.immutable && plasmoid.userConfiguring);
})
var container = appletContainerComponent.createObject(root, {
applet: applet,
visible: visibleBinding,
inThickArea: false
});
applet.parent = container;
applet.anchors.fill = container;
applet.visible = visibleBinding;
// Is there a DND placeholder? Replace it!
if (dndSpacer.parent === currentLayout) {
LayoutManager.insertBefore(dndSpacer, container);
dndSpacer.parent = root;
LayoutManager.updateMargins();
return;
// If the provided position is valid, use it.
} else if (x >= 0 && y >= 0) {
var index = LayoutManager.insertAtCoordinates(container, x , y);
// Fall through to determining an appropriate insert position.
} else {
var before = lastSpacer;
container.animationsEnabled = false;
// 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 (!startupTimer.running && applet.pluginName === "org.kde.plasma.icon") {
var middle = currentLayout.childAt(root.width / 2, root.height / 2);
if (middle) {
before = middle;
}
// lastSpacer is here, enqueue before it.
}
LayoutManager.insertBefore(before, container);
//event compress the enable of animations
startupTimer.restart();
}
LayoutManager.updateMargins();
}
function checkLastSpacer() {
var flexibleFound = false;
for (var i = 0; i < currentLayout.children.length; ++i) {
var applet = currentLayout.children[i].applet;
if (!applet) {
continue;
}
if (!applet.visible || !applet.Layout) {
continue;
}
if ((root.isHorizontal && applet.Layout.fillWidth) ||
(!root.isHorizontal && applet.Layout.fillHeight)) {
flexibleFound = true;
break
}
}
lastSpacer.visible= !flexibleFound;
}
//END functions
//BEGIN connections
Component.onCompleted: {
LayoutManager.plasmoid = plasmoid;
LayoutManager.root = root;
LayoutManager.layout = currentLayout;
LayoutManager.lastSpacer = lastSpacer;
LayoutManager.marginHighlights = [];
LayoutManager.restore();
plasmoid.action("configure").visible = Qt.binding(function() {
return !plasmoid.immutable;
});
plasmoid.action("configure").enabled = Qt.binding(function() {
return !plasmoid.immutable;
});
}
onDragEnter: {
if (plasmoid.immutable) {
event.ignore();
return;
}
//during drag operations we disable panel auto resize
if (root.isHorizontal) {
root.fixedWidth = root.width
} else {
root.fixedHeight = root.height
}
LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y)
}
onDragMove: {
LayoutManager.insertAtCoordinates(dndSpacer, event.x, event.y);
}
onDragLeave: {
dndSpacer.parent = root;
root.fixedWidth = 0;
root.fixedHeight = 0;
}
onDrop: {
plasmoid.processMimeData(event.mimeData, event.x, event.y);
event.accept(event.proposedAction);
root.fixedWidth = 0;
root.fixedHeight = 0;
}
Containment.onAppletAdded: {
addApplet(applet, x, y);
LayoutManager.save();
}
Containment.onAppletRemoved: {
LayoutManager.removeApplet(applet);
LayoutManager.save();
}
Plasmoid.onUserConfiguringChanged: {
if (plasmoid.immutable) {
if (dragOverlay) {
dragOverlay.destroy();
}
return;
}
if (plasmoid.userConfiguring) {
for (var i = 0; i < plasmoid.applets.length; ++i) {
plasmoid.applets[i].expanded = false;
}
if (!dragOverlay) {
var component = Qt.createComponent("ConfigOverlay.qml");
if (component.status === Component.Ready) {
dragOverlay = component.createObject(root);
} else {
console.log("Could not create ConfigOverlay:", component.errorString());
}
component.destroy();
} else {
dragOverlay.visible = true;
}
} else {
dragOverlay.destroy();
}
}
onToolBoxChanged: {
if (startupTimer.running) {
startupTimer.restart();
}
}
//END connections
//BEGIN components
Component {
id: appletContainerComponent
// This loader conditionally manages the BusyIndicator, it's not
// loading the applet. The applet becomes a regular child item.
Loader {
id: container
visible: false
property bool inThickArea: false
property bool isAppletContainer: true
property bool animationsEnabled: true
//when the applet moves caused by its resize, don't animate.
//this is completely heuristic, but looks way less "jumpy"
property bool movingForResize: false
Layout.fillWidth: applet && applet.Layout.fillWidth
Layout.onFillWidthChanged: {
if (plasmoid.formFactor !== PlasmaCore.Types.Vertical) {
checkLastSpacer();
}
}
Layout.fillHeight: applet && applet.Layout.fillHeight
Layout.onFillHeightChanged: {
if (plasmoid.formFactor === PlasmaCore.Types.Vertical) {
checkLastSpacer();
}
}
function getMargins(side, returnAllMargins = false) {
//Margins are either the size of the margins in the SVG, unless that prevents the panel from being at least half a smallMedium icon + smallSpace) tall at which point we set the margin to whatever allows it to be that...or if it still won't fit, 1.
var layout = {
top: currentLayout.isLayoutHorizontal, bottom: currentLayout.isLayoutHorizontal,
right: !currentLayout.isLayoutHorizontal, left: !currentLayout.isLayoutHorizontal
};
var fillArea = applet && (applet.constraintHints & PlasmaCore.Types.CanFillArea);
return ((layout[side] || returnAllMargins) && !fillArea) ? Math.round(Math.min(spacingAtMinSize, (inThickArea ? thickPanelSvg.fixedMargins[side] : panelSvg.fixedMargins[side]))) : 0;
}
Layout.topMargin: getMargins('top')
Layout.bottomMargin: getMargins('bottom')
Layout.leftMargin: getMargins('left')
Layout.rightMargin: getMargins('right')
Layout.minimumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumWidth > 0 ? applet.Layout.minimumWidth : root.height) : root.width) - Layout.leftMargin - Layout.rightMargin
Layout.minimumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.minimumHeight > 0 ? applet.Layout.minimumHeight : root.width) : root.height) - Layout.bottomMargin - Layout.topMargin
Layout.preferredWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredWidth > 0 ? applet.Layout.preferredWidth : root.height) : root.width) - Layout.leftMargin - Layout.rightMargin
Layout.preferredHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.preferredHeight > 0 ? applet.Layout.preferredHeight : root.width) : root.height) - Layout.bottomMargin - Layout.topMargin
Layout.maximumWidth: (currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumWidth > 0 ? applet.Layout.maximumWidth : (Layout.fillWidth ? root.width : root.height)) : root.height) - Layout.leftMargin - Layout.rightMargin
Layout.maximumHeight: (!currentLayout.isLayoutHorizontal ? (applet && applet.Layout.maximumHeight > 0 ? applet.Layout.maximumHeight : (Layout.fillHeight ? root.height : root.width)) : root.width) - Layout.bottomMargin - Layout.topMargin
property int oldX: x
property int oldY: y
property Item applet
onAppletChanged: {
if (!applet) {
destroy();
}
}
active: applet && applet.busy
sourceComponent: PlasmaComponents.BusyIndicator {}
Layout.onMinimumWidthChanged: movingForResize = true;
Layout.onMinimumHeightChanged: movingForResize = true;
Layout.onMaximumWidthChanged: movingForResize = true;
Layout.onMaximumHeightChanged: movingForResize = true;
onXChanged: {
if (movingForResize) {
movingForResize = false;
return;
}
if (!animationsEnabled) {
startupTimer.restart();
return;
}
translation.x = oldX - x
translation.y = oldY - y
translAnim.running = true
oldX = x
oldY = y
}
onYChanged: {
if (movingForResize) {
movingForResize = false;
return;
}
if (!animationsEnabled) {
startupTimer.restart();
return;
}
translation.x = oldX - x
translation.y = oldY - y
translAnim.running = true
oldX = x
oldY = y
}
transform: Translate {
id: translation
}
NumberAnimation {
id: translAnim
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
target: translation
properties: "x,y"
to: 0
}
}
}
Component {
id: rectHighlightEl
Item {
visible: plasmoid.editMode && marginAreasEnabled
property Item startApplet
property Item endApplet
property bool thickArea
component HighlightPart: Item {
property bool topSide
property string part
// I don't know if the panel is vertical or horizontal, so I'll use panel
// (w) width and (h) height as a (w, h) coordinate system, defining two helper
// functions to switch between it and cartesian (x, y).
property bool horizontal: plasmoid.formFactor === PlasmaCore.Types.Horizontal
property int mod: topSide ? 1 : -1
property string svgSide: horizontal ? (topSide ? 'top' : 'bottom') : (topSide ? 'left' : 'right')
// Panel To Cartesian
property var ptc: ({
w: horizontal ? 'x' : 'y', width: horizontal ? 'width' : 'height',
h: horizontal ? 'y' : 'x', height: horizontal ? 'height' : 'width'
})
// Cartesian to Panel
property var ctp: ({
x: horizontal ? 'w' : 'h', width: horizontal ? 'width' : 'height',
y: horizontal ? 'h' : 'w', height: horizontal ? 'height' : 'width'
})
property var positions: ({
fill: {
w: startApplet ? (startApplet[ptc.w] + startApplet[ptc.width]) : -panelSvg.margins[horizontal ? 'left' : 'top'],
get width() {return positions.step.w - positions.fill.w},
get h() {return topSide ? 0 : root[ptc.height]-this.height},
height: Math.min(spacingAtMinSize, (thickArea ? thickPanelSvg : panelSvg).fixedMargins[svgSide]),
elementId: 'fill', visible: true
},
step: {
w: endApplet ? endApplet[ptc.w] : root[ptc.width] + panelSvg.margins[horizontal ? 'right' : 'bottom'],
width: endApplet ? endApplet[ptc.width] : 0,
get h() {return (topSide ? 0 : root[ptc.height]-this.height)+mod*panelSvg.fixedMargins[svgSide]},
height: Math.min(spacingAtMinSize, thickPanelSvg.fixedMargins[svgSide]) - Math.min(spacingAtMinSize, panelSvg.fixedMargins[svgSide]),
elementId: ((horizontal ? topSide : thickArea) ? 'top' : 'bottom') + ((horizontal ? thickArea : topSide) ? "left" : "right"),
visible: endApplet
},
filledstep: {
get w() {return positions.step.w},
get width() {return positions.step.width},
get h() {return topSide ? 0 : root[ptc.height]-this.height},
height: Math.min(spacingAtMinSize, panelSvg.fixedMargins[svgSide]),
elementId: 'fill', visible: endApplet
}
})
PlasmaCore.SvgItem {
svg: marginHighlightSvg
elementId: positions[part].elementId
x: positions[part][ctp.x]
y: positions[part][ctp.y]
width: positions[part][ctp.width]
height: positions[part][ctp.height]
visible: positions[part].elementId
}
}
HighlightPart{topSide: true; part: 'fill'}
HighlightPart{topSide: true; part: 'step'}
HighlightPart{topSide: true; part: 'filledstep'}
HighlightPart{topSide: false; part: 'fill'}
HighlightPart{topSide: false; part: 'step'}
HighlightPart{topSide: false; part: 'filledstep'}
}
}
//END components
//BEGIN UI elements
anchors {
leftMargin: currentLayout.isLayoutHorizontal ? Math.min(spacingAtMinSize, panelSvg.fixedMargins.left) : 0
rightMargin: currentLayout.isLayoutHorizontal ? Math.min(spacingAtMinSize, panelSvg.fixedMargins.right) : 0
topMargin: currentLayout.isLayoutHorizontal ? 0 : Math.min(spacingAtMinSize, panelSvg.fixedMargins.top)
bottomMargin: currentLayout.isLayoutHorizontal ? 0 : Math.min(spacingAtMinSize, panelSvg.fixedMargins.bottom)
}
Item {
id: lastSpacer
parent: currentLayout
Layout.fillWidth: true
Layout.fillHeight: true
}
Item {
id: dndSpacer
Layout.preferredWidth: width
Layout.preferredHeight: height
width: (plasmoid.formFactor === PlasmaCore.Types.Vertical) ? currentLayout.width : PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).width * 10
height: (plasmoid.formFactor === PlasmaCore.Types.Vertical) ? PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).width * 10 : currentLayout.height
}
// while the user is moving the applet when configuring the panel, the applet is reparented
// here so it can be moved freely; previously it was reparented to "root" but this one does not
// take into account the toolbox (which is left-of) the layout in right-to-left languages
Item {
id: moveAppletLayer
anchors.fill: currentLayout
}
GridLayout {
id: currentLayout
readonly property bool isLayoutHorizontal: root.isHorizontal
rowSpacing: PlasmaCore.Units.smallSpacing
columnSpacing: PlasmaCore.Units.smallSpacing
x: (isLayoutHorizontal && root.toolBox && Qt.application.layoutDirection === Qt.RightToLeft && plasmoid.editMode) ? root.toolBox.width : 0;
y: 0
width: root.width - (isLayoutHorizontal && root.toolBox && plasmoid.editMode ? root.toolBox.width : 0)
height: root.height - (!isLayoutHorizontal && root.toolBox && plasmoid.editMode ? root.toolBox.height : 0)
Layout.preferredWidth: {
var width = 0;
for (var i = 0, length = currentLayout.children.length; i < length; ++i) {
var item = currentLayout.children[i];
if (item.Layout) {
width += Math.max(item.Layout.minimumWidth, item.Layout.preferredWidth);
}
}
return width;
}
Layout.preferredHeight: {
var height = 0;
for (var i = 0, length = currentLayout.children.length; i < length; ++i) {
var item = currentLayout.children[i];
if (item.Layout) {
height += Math.max(item.Layout.minimumHeight, item.Layout.preferredHeight);
}
}
return height;
}
rows: 1
columns: 1
//when horizontal layout top-to-bottom, this way it will obey our limit of one row and actually lay out left to right
flow: isLayoutHorizontal ? GridLayout.TopToBottom : GridLayout.LeftToRight
layoutDirection: Qt.application.layoutDirection
}
onWidthChanged: {
if (startupTimer.running) {
startupTimer.restart();
}
}
onHeightChanged: {
if (startupTimer.running) {
startupTimer.restart();
}
}
//FIXME: I don't see other ways at the moment a way to see when the UI is REALLY ready
Timer {
id: startupTimer
interval: 4000
onTriggered: {
for (var i = 0; i < currentLayout.children.length; ++i) {
var item = currentLayout.children[i];
if (item.hasOwnProperty("animationsEnabled")) {
item.animationsEnabled = true;
}
}
}
}
//END UI elements
}