112 lines
3.4 KiB
QML
112 lines
3.4 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Shapes 1.15
|
|
import QtGraphicalEffects 1.15
|
|
|
|
Item {
|
|
id: control
|
|
property color color
|
|
property int radius: 0
|
|
property int topLeftRadius: radius
|
|
property int topRightRadius: radius
|
|
property int bottomLeftRadius: radius
|
|
property int bottomRightRadius: radius
|
|
property int topPadding: 0
|
|
property int leftPadding: 0
|
|
property int rightPadding: 0
|
|
property int bottomPadding: 0
|
|
property real borderWidth: 0
|
|
property string borderColor: "transparent"
|
|
default property alias contentItem: container.data
|
|
|
|
onColorChanged: shape.requestPaint()
|
|
onBorderColorChanged: border.requestPaint()
|
|
|
|
Canvas {
|
|
id: shape
|
|
anchors.fill: parent
|
|
layer.enabled: true
|
|
layer.samples: 4
|
|
|
|
onPaint: {
|
|
var ctx = getContext("2d");
|
|
ctx.clearRect(0, 0, width, height);
|
|
|
|
var tl = control.topLeftRadius;
|
|
var tr = control.topRightRadius;
|
|
var br = control.bottomRightRadius;
|
|
var bl = control.bottomLeftRadius;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(tl, 0);
|
|
ctx.lineTo(width - tr, 0);
|
|
ctx.arc(width - tr, tr, tr, -Math.PI / 2, 0, false); // top-right
|
|
ctx.lineTo(width, height - br);
|
|
ctx.arc(width - br, height - br, br, 0, Math.PI / 2, false); // bottom-right
|
|
ctx.lineTo(bl, height);
|
|
ctx.arc(bl, height - bl, bl, Math.PI / 2, Math.PI, false); // bottom-left
|
|
ctx.lineTo(0, tl);
|
|
ctx.arc(tl, tl, tl, Math.PI, Math.PI * 3 / 2, false); // top-left
|
|
ctx.closePath();
|
|
|
|
ctx.fillStyle = control.color;
|
|
ctx.fill();
|
|
}
|
|
}
|
|
|
|
Canvas {
|
|
id: border
|
|
width: shape.width
|
|
height: shape.height
|
|
anchors.centerIn: parent
|
|
layer.enabled: true
|
|
layer.samples: 4
|
|
|
|
onPaint: {
|
|
var ctx = getContext("2d");
|
|
ctx.clearRect(0, 0, width, height);
|
|
|
|
var tl = control.topLeftRadius;
|
|
var tr = control.topRightRadius;
|
|
var br = control.bottomRightRadius;
|
|
var bl = control.bottomLeftRadius;
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(tl, 0);
|
|
ctx.lineTo(width - tr, 0);
|
|
ctx.arc(width - tr, tr, tr, -Math.PI / 2, 0, false); // top-right
|
|
ctx.lineTo(width, height - br);
|
|
ctx.arc(width - br, height - br, br, 0, Math.PI / 2, false); // bottom-right
|
|
ctx.lineTo(bl, height);
|
|
ctx.arc(bl, height - bl, bl, Math.PI / 2, Math.PI, false); // bottom-left
|
|
ctx.lineTo(0, tl);
|
|
ctx.arc(tl, tl, tl, Math.PI, Math.PI * 3 / 2, false); // top-left
|
|
ctx.closePath();
|
|
|
|
ctx.strokeStyle = control.borderColor;
|
|
ctx.lineWidth = control.borderWidth * 2;
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
|
|
Item{
|
|
id: container
|
|
anchors{
|
|
fill: parent
|
|
topMargin: control.topPadding
|
|
bottomMargin: control.bottomPadding
|
|
leftMargin: control.leftPadding
|
|
rightMargin: control.rightPadding
|
|
}
|
|
clip: true
|
|
layer.enabled: true
|
|
layer.effect: OpacityMask {
|
|
visible: false
|
|
implicitHeight: container.height
|
|
implicitWidth: container.width
|
|
maskSource: shape
|
|
invert: control.color.a === 0
|
|
}
|
|
}
|
|
}
|