added quickshell
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
import QtQuick
|
||||
import QtQuick.Shapes
|
||||
import QtQuick.Effects
|
||||
import "root:/config"
|
||||
import "root:/components"
|
||||
|
||||
// The base surface for everything in this shell: a leaning, corner-chopped slab
|
||||
// with an optional halftone wash and a crimson slash along its leading edge.
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property color fill: Theme.surface
|
||||
property real fillOpacity: 0.94
|
||||
property color border: Theme.outline
|
||||
property real borderWidth: Theme.stroke
|
||||
|
||||
// Lean of the vertical edges, as a fraction of height. 0 = upright.
|
||||
property real lean: Theme.skew
|
||||
property bool leanLeft: false
|
||||
|
||||
// Corner chop size, and which corners get chopped (indices into the
|
||||
// polygon, clockwise from the top-left). Default chops the two corners that
|
||||
// read as "cut" against the lean.
|
||||
property real chop: Theme.cut
|
||||
property var chopCorners: [1, 3]
|
||||
|
||||
// Crimson slash down the leading edge — the Persona 5 tell.
|
||||
property bool slash: false
|
||||
property color slashColor: Theme.accent
|
||||
property real slashWidth: 4
|
||||
|
||||
// Screen-printed dot wash.
|
||||
property bool halftone: false
|
||||
property color halftoneColor: Theme.primary
|
||||
property real halftoneOpacity: 0.07
|
||||
|
||||
// Inner glow along the top edge, for panels that should feel backlit.
|
||||
property bool sheen: false
|
||||
|
||||
readonly property real leanInset: height * Math.abs(lean)
|
||||
readonly property var polygon: leanLeft
|
||||
? Geom.parallelogramL(width, height, lean)
|
||||
: Geom.parallelogram(width, height, lean)
|
||||
|
||||
// Child content lives inside `contentItem`, inset on both sides far enough
|
||||
// to clear the slanted edges. Panels do not auto-size: callers set implicit
|
||||
// sizes from their own layout (`row.implicitWidth + contentPad * 2`), which
|
||||
// keeps the shape maths out of every binding loop.
|
||||
default property alias content: contentHolder.data
|
||||
readonly property alias contentItem: contentHolder
|
||||
property real padding: Theme.padM
|
||||
|
||||
readonly property real contentPad: padding + leanInset
|
||||
|
||||
Shape {
|
||||
id: body
|
||||
anchors.fill: parent
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
asynchronous: false
|
||||
|
||||
ShapePath {
|
||||
fillColor: Theme.alpha(root.fill, root.fillOpacity)
|
||||
strokeColor: root.borderWidth > 0 ? root.border : "transparent"
|
||||
strokeWidth: root.borderWidth
|
||||
joinStyle: ShapePath.MiterJoin
|
||||
capStyle: ShapePath.FlatCap
|
||||
|
||||
PathPolyline {
|
||||
path: Geom.chamfer(root.polygon, root.chop, root.chopCorners)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Halftone wash, masked to the panel silhouette.
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: root.halftone
|
||||
asynchronous: true
|
||||
sourceComponent: Item {
|
||||
Shape {
|
||||
id: maskShape
|
||||
anchors.fill: parent
|
||||
visible: false
|
||||
layer.enabled: true
|
||||
layer.smooth: true
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
ShapePath {
|
||||
fillColor: "white"
|
||||
strokeColor: "transparent"
|
||||
PathPolyline {
|
||||
path: Geom.chamfer(root.polygon, root.chop, root.chopCorners)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Theme.texHalftone
|
||||
fillMode: Image.Tile
|
||||
opacity: root.halftoneOpacity
|
||||
smooth: false
|
||||
layer.enabled: true
|
||||
layer.effect: MultiEffect {
|
||||
colorization: 1.0
|
||||
colorizationColor: root.halftoneColor
|
||||
maskEnabled: true
|
||||
maskSource: maskShape
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Backlit top edge.
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: root.sheen
|
||||
sourceComponent: Shape {
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
ShapePath {
|
||||
strokeColor: "transparent"
|
||||
fillGradient: LinearGradient {
|
||||
x1: 0; y1: 0; x2: 0; y2: root.height
|
||||
GradientStop { position: 0.0; color: Theme.alpha(Theme.primary, 0.16) }
|
||||
GradientStop { position: 0.55; color: "transparent" }
|
||||
}
|
||||
PathPolyline {
|
||||
path: Geom.chamfer(root.polygon, root.chop, root.chopCorners)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Leading-edge slash.
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
active: root.slash
|
||||
sourceComponent: Shape {
|
||||
preferredRendererType: Shape.CurveRenderer
|
||||
ShapePath {
|
||||
fillColor: root.slashColor
|
||||
strokeColor: "transparent"
|
||||
PathPolyline {
|
||||
path: {
|
||||
const off = root.height * root.lean;
|
||||
const w = root.slashWidth;
|
||||
return root.leanLeft
|
||||
? Geom.closed([Qt.point(0, 0), Qt.point(w, 0),
|
||||
Qt.point(off + w, root.height), Qt.point(off, root.height)])
|
||||
: Geom.closed([Qt.point(off, 0), Qt.point(off + w, 0),
|
||||
Qt.point(w, root.height), Qt.point(0, root.height)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: contentHolder
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: root.contentPad
|
||||
anchors.rightMargin: root.contentPad
|
||||
anchors.topMargin: root.padding
|
||||
anchors.bottomMargin: root.padding
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user