Files

143 lines
6.2 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Modules.SurfaceWidgets
import qs.DCommon.Widgets
import qs.Widgets
import "OverflowLayout.js" as OverflowLayout
Item {
id: root
required property var sectionContext
readonly property alias button: button
property bool wantOpen: false
readonly property var popout: popupLoader.item
readonly property bool open: popout?.shouldBeVisible ?? false
readonly property var popupParent: popout?.contentLoader.item?.widgetHost ?? null
readonly property var entries: sectionContext.hiddenEntries
readonly property real naturalWidth: entries.reduce((width, entry) => Math.max(width, entry.itemWidth), 0)
readonly property real naturalHeight: entries.reduce((height, entry) => height + entry.itemHeight, 0) + Math.max(0, entries.length - 1) * Theme.spacingS
readonly property real popupWidth: Math.min(naturalWidth + Theme.spacingS * 2, (sectionContext.parentScreen?.width ?? Infinity) - Theme.spacingL * 2)
readonly property real popupHeight: Math.min(naturalHeight + Theme.spacingS * 2, (sectionContext.parentScreen?.height ?? Infinity) - Theme.spacingL * 2)
readonly property real contentWidth: Math.max(naturalWidth, popupWidth - Theme.spacingS * 2)
onWantOpenChanged: sectionContext.overflowWanted = wantOpen
Component.onDestruction: sectionContext.overflowWanted = false
onEntriesChanged: positionEntries()
onNaturalHeightChanged: positionEntries()
onContentWidthChanged: positionEntries()
function positionEntries() {
let y = 0;
for (const entry of entries) {
entry.popupX = (contentWidth - entry.itemWidth) / 2;
entry.popupY = y;
y += entry.itemHeight + Theme.spacingS;
}
}
function toggle() {
if (open) {
popout.close();
return;
}
if (popout)
showPopout();
else
wantOpen = true;
}
function showPopout() {
if (!sectionContext.surfaceContext?.positionPopout(popout, button, sectionContext.section)) {
wantOpen = false;
return;
}
positionEntries();
PopoutManager.requestPopout(popout, undefined, "bar-overflow-" + (sectionContext.barConfig?.id ?? "") + "-" + sectionContext.section);
}
BarPill {
id: button
parent: root.sectionContext
axis: root.sectionContext.axis
section: root.sectionContext.section
parentScreen: root.sectionContext.parentScreen
widgetThickness: root.sectionContext.widgetThickness
barThickness: root.sectionContext.barThickness
barSpacing: root.sectionContext.barSpacing
barConfig: root.sectionContext.barConfig
widgetBackground: root.sectionContext.overflowBackground
sectionSpacing: root.sectionContext.widgetSpacing
segmentRole: root.sectionContext.overflowSegmentRole
isFirst: root.sectionContext.inlineOrder[0] === -1
isLast: root.sectionContext.inlineOrder[root.sectionContext.inlineOrder.length - 1] === -1
isLeftBarEdge: !root.sectionContext.isVertical && section === "left" && root.sectionContext.edgeIsScreenEdge
isRightBarEdge: !root.sectionContext.isVertical && section === "right" && root.sectionContext.edgeIsScreenEdge
isTopBarEdge: root.sectionContext.isVertical && section === "left" && root.sectionContext.edgeIsScreenEdge
isBottomBarEdge: root.sectionContext.isVertical && section === "right" && root.sectionContext.edgeIsScreenEdge
crossEdgeExtension: !root.sectionContext.isVertical && section !== "center" ? root.sectionContext.crossEdgeExtension : 0
blurBarWindow: root.sectionContext.blurBarWindow
x: root.sectionContext.isVertical ? (root.sectionContext.width - width) / 2 : root.sectionContext.overflowButtonPosition
y: root.sectionContext.isVertical ? root.sectionContext.overflowButtonPosition : (root.sectionContext.height - height) / 2
activeFocusOnTab: true
Accessible.role: Accessible.Button
Accessible.name: I18n.tr("More widgets", "accessible name of the bar overflow button")
Accessible.description: I18n.tr("Overflow") + ": " + root.sectionContext.overflowCount
onClicked: root.toggle()
Keys.onSpacePressed: event => {
root.toggle();
event.accepted = true;
}
Keys.onReturnPressed: event => {
root.toggle();
event.accepted = true;
}
content: Component {
Item {
implicitWidth: Math.max(0, root.button.widgetThickness - root.button.horizontalPadding * 2)
implicitHeight: implicitWidth
DIcon {
anchors.centerIn: parent
name: OverflowLayout.expanderIcon(root.sectionContext.axis?.edge, root.open)
size: Theme.iconSizeSmall
color: Theme.widgetTextColor
}
}
}
}
Loader {
id: popupLoader
active: root.wantOpen
onLoaded: root.showPopout()
sourceComponent: Component {
DPopout {
layerNamespace: "dms:bar-overflow"
screen: root.sectionContext.parentScreen
popupWidth: root.popupWidth
popupHeight: root.popupHeight
onBackgroundClicked: close()
onCloseAnimationFinished: root.wantOpen = false
content: Component {
Item {
readonly property var widgetHost: scroller.contentItem
// A hosted widget holding focus would starve the popout's own Escape handler.
Keys.onEscapePressed: root.popout?.close()
DFlickable {
id: scroller
anchors.fill: parent
anchors.margins: Theme.spacingS
contentWidth: root.contentWidth
contentHeight: root.naturalHeight
flickableDirection: Flickable.AutoFlickIfNeeded
clip: true
}
}
}
}
}
}
}