Skip to content

Commit a310c86

Browse files
committed
LateNightQML: add mixer
1 parent 17be527 commit a310c86

21 files changed

Lines changed: 1645 additions & 123 deletions
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import QtQuick
2+
import "../../../qml" as Skin
3+
import "../LateNightTheme"
4+
5+
Skin.ControlFader {
6+
id: root
7+
8+
property int backgroundMargin: 0
9+
property alias backgroundSource: backgroundImage.source
10+
property bool centeredBar: false
11+
property real centeredBarAxis: height / 2
12+
property alias handleSource: handleImage.source
13+
property color valueLineColor: LateNightTheme.mixerSliderBarColor
14+
15+
bar: !centeredBar
16+
barColor: valueLineColor
17+
barMargin: 8
18+
barWidth: 2
19+
implicitHeight: backgroundImage.implicitHeight + (backgroundMargin * 2)
20+
implicitWidth: backgroundImage.implicitWidth + (backgroundMargin * 2)
21+
showDefaultHandle: false
22+
23+
background: Image {
24+
id: backgroundImage
25+
26+
anchors.fill: parent
27+
anchors.margins: root.backgroundMargin
28+
fillMode: Image.PreserveAspectFit
29+
}
30+
handle: Image {
31+
id: handleImage
32+
33+
fillMode: Image.PreserveAspectFit
34+
height: implicitHeight
35+
width: implicitWidth
36+
x: root.horizontal ? root.visualPosition * (root.width - width) : (root.width - width) / 2
37+
y: root.vertical ? root.visualPosition * (root.height - height) : (root.height - height) / 2
38+
}
39+
40+
Rectangle {
41+
readonly property real handleCenter: handleImage.x + handleImage.width / 2
42+
readonly property real start: root.width / 2
43+
44+
color: root.valueLineColor
45+
height: root.barWidth
46+
radius: height / 2
47+
visible: root.centeredBar && root.horizontal && width > 0
48+
width: Math.abs(handleCenter - start)
49+
x: Math.min(start, handleCenter)
50+
y: root.centeredBarAxis - height / 2
51+
z: 1
52+
}
53+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import Mixxx 1.0 as Mixxx
2+
import QtQuick
3+
import "../LateNightTheme"
4+
5+
Item {
6+
id: root
7+
8+
property int backgroundVariant: 0
9+
property real clipThreshold: 0.98
10+
readonly property bool clipping: peakIndicatorControl.value > 0 || levelControl.value >= clipThreshold
11+
property bool drawGroove: true
12+
required property string group
13+
readonly property real level: Math.max(0, Math.min(1, levelControl.value))
14+
property string levelKey: "vu_meter"
15+
property string peakKey: "peak_indicator"
16+
readonly property string variantName: backgroundVariant === 0 ? "dark" : "light"
17+
18+
clip: true
19+
implicitHeight: 96
20+
implicitWidth: 8
21+
22+
Rectangle {
23+
anchors.horizontalCenter: parent.horizontalCenter
24+
color: "#040404"
25+
height: parent.height
26+
visible: root.drawGroove
27+
width: 8
28+
}
29+
Image {
30+
anchors.horizontalCenter: parent.horizontalCenter
31+
fillMode: Image.PreserveAspectFit
32+
height: 11
33+
smooth: false
34+
source: LateNightTheme.mixerVuClipBackground(root.variantName)
35+
width: 6
36+
y: 1
37+
}
38+
Image {
39+
anchors.bottom: parent.bottom
40+
anchors.bottomMargin: 1
41+
anchors.horizontalCenter: parent.horizontalCenter
42+
fillMode: Image.PreserveAspectFit
43+
height: 81
44+
smooth: false
45+
source: LateNightTheme.mixerVuLevelBackground(root.variantName)
46+
width: 6
47+
}
48+
Image {
49+
anchors.horizontalCenter: parent.horizontalCenter
50+
fillMode: Image.PreserveAspectFit
51+
height: 11
52+
opacity: root.clipping ? 1 : 0
53+
smooth: false
54+
source: LateNightTheme.lateNightAsset("style", "vu_deck_clipping_active.png")
55+
width: 6
56+
y: 1
57+
}
58+
Item {
59+
anchors.bottom: parent.bottom
60+
anchors.bottomMargin: 1
61+
anchors.horizontalCenter: parent.horizontalCenter
62+
clip: true
63+
height: 81 * root.level
64+
width: 6
65+
66+
Image {
67+
anchors.bottom: parent.bottom
68+
anchors.horizontalCenter: parent.horizontalCenter
69+
fillMode: Image.PreserveAspectFit
70+
height: 81
71+
smooth: false
72+
source: LateNightTheme.lateNightAsset("style", "vu_deck_level_active.png")
73+
width: 6
74+
}
75+
}
76+
Mixxx.ControlProxy {
77+
id: levelControl
78+
79+
group: root.group
80+
key: root.levelKey
81+
}
82+
Mixxx.ControlProxy {
83+
id: peakIndicatorControl
84+
85+
group: root.group
86+
key: root.peakKey
87+
}
88+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import QtQuick
2+
import "../../../qml" as Skin
3+
import "../LateNightTheme"
4+
5+
Skin.ControlKnob {
6+
id: root
7+
8+
readonly property int arcRenderScale: 8
9+
property url backgroundSource: LateNightTheme.assetRegularKnobBackground
10+
property bool displayArc: false
11+
property color displayArcColor: "transparent"
12+
property real displayArcOffsetY: 1.998
13+
property real displayArcRadius: 12.5
14+
property int displayArcStart: 1 // Knob.ArcStart.Center
15+
property real displayArcWidth: 2
16+
property string indicatorColor: "orange"
17+
property string indicatorKind: "regular"
18+
19+
angle: 135
20+
arc: false
21+
arcStart: displayArcStart
22+
color: displayArcColor
23+
implicitHeight: backgroundImage.implicitHeight
24+
implicitWidth: backgroundImage.implicitWidth
25+
knobCenterOffsetY: displayArcOffsetY
26+
showDefaultBackground: false
27+
showDefaultForeground: false
28+
29+
background: Image {
30+
id: backgroundImage
31+
32+
anchors.fill: parent
33+
fillMode: Image.PreserveAspectFit
34+
source: root.backgroundSource
35+
}
36+
foreground: Item {
37+
anchors.fill: parent
38+
39+
Image {
40+
anchors.fill: parent
41+
fillMode: Image.PreserveAspectFit
42+
source: LateNightTheme.mixerKnobIndicator(root.indicatorKind, root.indicatorColor)
43+
}
44+
}
45+
46+
Canvas {
47+
id: arcCanvas
48+
49+
readonly property color renderedColor: root.displayArcColor
50+
readonly property real renderedOffsetY: root.displayArcOffsetY
51+
readonly property real renderedRadius: root.displayArcRadius
52+
readonly property int renderedStart: root.displayArcStart
53+
readonly property real renderedValue: root.value
54+
readonly property real renderedWidth: root.displayArcWidth
55+
56+
antialiasing: true
57+
height: root.height * root.arcRenderScale
58+
layer.enabled: true
59+
layer.mipmap: true
60+
renderStrategy: Canvas.Immediate
61+
scale: 1 / root.arcRenderScale
62+
transformOrigin: Item.TopLeft
63+
visible: root.displayArc
64+
width: root.width * root.arcRenderScale
65+
z: 1
66+
67+
Component.onCompleted: requestPaint()
68+
onPaint: {
69+
const ctx = getContext("2d");
70+
ctx.clearRect(0, 0, width, height);
71+
if (!root.displayArc) {
72+
return;
73+
}
74+
75+
const renderScale = root.arcRenderScale;
76+
const startAngle = root.angleFrom(root.arcStartValue - root.valueCenter) - 90;
77+
const sweepAngle = root.angleFrom(root.value - root.arcStartValue);
78+
const startRadians = startAngle * Math.PI / 180;
79+
const endRadians = (startAngle + sweepAngle) * Math.PI / 180;
80+
81+
ctx.beginPath();
82+
ctx.strokeStyle = root.displayArcColor;
83+
ctx.lineWidth = root.displayArcWidth * renderScale;
84+
ctx.lineCap = "round";
85+
ctx.arc((root.width / 2) * renderScale, (root.height / 2 + root.displayArcOffsetY) * renderScale, root.displayArcRadius * renderScale, startRadians, endRadians, sweepAngle < 0);
86+
ctx.stroke();
87+
}
88+
onRenderedColorChanged: requestPaint()
89+
onRenderedOffsetYChanged: requestPaint()
90+
onRenderedRadiusChanged: requestPaint()
91+
onRenderedStartChanged: requestPaint()
92+
onRenderedValueChanged: requestPaint()
93+
onRenderedWidthChanged: requestPaint()
94+
onVisibleChanged: requestPaint()
95+
}
96+
}

0 commit comments

Comments
 (0)