forked from Shinonome/dots-hyprland
waffles: more continuous infinite scrolling calendar
This commit is contained in:
@@ -231,5 +231,13 @@ Singleton {
|
||||
easing.bezierCurve: transition.easing.bezierCurve.easeIn
|
||||
}
|
||||
}
|
||||
|
||||
property Component scroll: Component {
|
||||
NumberAnimation {
|
||||
duration: 250
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: [0.0, 0.0, 0.25, 1.0, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ Button {
|
||||
property color colBackgroundToggledActive: Looks.colors.accentActive
|
||||
property color colForeground: Looks.colors.fg
|
||||
property color colForegroundToggled: Looks.colors.accentFg
|
||||
property color colForegroundDisabled: ColorUtils.transparentize(Looks.colors.subfg, 0.4)
|
||||
property alias backgroundOpacity: backgroundRect.opacity
|
||||
property color color: {
|
||||
if (!root.enabled) return colBackground;
|
||||
@@ -37,7 +38,11 @@ Button {
|
||||
return root.colBackground;
|
||||
}
|
||||
}
|
||||
property color fgColor: root.checked ? root.colForegroundToggled : root.colForeground
|
||||
property color fgColor: {
|
||||
if (root.checked) return root.colForegroundToggled
|
||||
if (root.enabled) return root.colForeground
|
||||
return root.colForegroundDisabled
|
||||
}
|
||||
property alias horizontalAlignment: buttonText.horizontalAlignment
|
||||
font {
|
||||
family: Looks.font.family.ui
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
// TODO: The overlaps are crazy, but the positioning approach works.
|
||||
// This could work well if we do it week by week instead of month by month.
|
||||
BodyRectangle {
|
||||
id: root
|
||||
|
||||
// State
|
||||
property bool collapsed
|
||||
|
||||
// Sizes
|
||||
property int _rowsPerMonth: 6
|
||||
property real viewHeight: (_rowsPerMonth * buttonSize) + ((_rowsPerMonth - 1) * buttonSpacing)
|
||||
property real buttonSize: 40
|
||||
property real buttonSpacing: 2
|
||||
property real spacePerExtraRow: buttonSize + buttonSpacing
|
||||
|
||||
implicitWidth: currentMonthGrid.implicitWidth
|
||||
implicitHeight: collapsed ? 0 : viewHeight
|
||||
opacity: implicitHeight > 0 ? 1 : 0
|
||||
|
||||
Behavior on implicitHeight {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
|
||||
// Month stuff
|
||||
property real targetMonthDiff: 0
|
||||
property real monthDiff: targetMonthDiff
|
||||
property int focusedMonthDiff: monthDiff // whole part of monthDiff
|
||||
property int currentMonth: DateTime.clock.date.getMonth() + 1 // 0-indexed -> 1-indexed
|
||||
property int currentYear: DateTime.clock.date.getFullYear()
|
||||
|
||||
clip: true
|
||||
property list<DiffMonthGrid> monthGrids: [previousPreviousMonthGrid, previousMonthGrid, currentMonthGrid, nextMonthGrid, nextNextMonthGrid]
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
y: {
|
||||
const origin = - currentMonthGrid.y;
|
||||
const diff = root.monthDiff * root.viewHeight;
|
||||
return origin + (-diff % root.viewHeight);
|
||||
}
|
||||
DiffMonthGrid {
|
||||
id: previousPreviousMonthGrid
|
||||
monthDiff: root.focusedMonthDiff - 2
|
||||
}
|
||||
DiffMonthGrid {
|
||||
id: previousMonthGrid
|
||||
monthDiff: root.focusedMonthDiff - 1
|
||||
}
|
||||
DiffMonthGrid {
|
||||
id: currentMonthGrid
|
||||
monthDiff: root.focusedMonthDiff
|
||||
}
|
||||
DiffMonthGrid {
|
||||
id: nextMonthGrid
|
||||
monthDiff: root.focusedMonthDiff + 1
|
||||
}
|
||||
DiffMonthGrid {
|
||||
id: nextNextMonthGrid
|
||||
monthDiff: root.focusedMonthDiff + 2
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: wheel => {
|
||||
root.targetMonthDiff += wheel.angleDelta.y / 120 * -0.333333; // Reverse cuz scrolling down should advance
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on monthDiff {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
|
||||
component DiffMonthGrid: MonthGrid {
|
||||
id: monthGrid
|
||||
required property int monthDiff
|
||||
property int index: root.monthGrids.indexOf(this)
|
||||
month: ((root.currentMonth - 1) + monthDiff) % 12 // 1-indexed -> 0-indexed
|
||||
year: root.currentYear + Math.floor((root.currentMonth - 1 + monthDiff) / 12)
|
||||
|
||||
spacing: root.buttonSpacing
|
||||
// background: Rectangle {
|
||||
// color: Qt.rgba(Math.abs(Math.sin(month * 12.9898)) % 1, Math.abs(Math.sin(month * 78.233)) % 1, Math.abs(Math.sin(month * 45.164)) % 1, 1)
|
||||
// }
|
||||
delegate: MonthDayButton {}
|
||||
}
|
||||
|
||||
component MonthDayButton: WButton {
|
||||
id: monthDayButton
|
||||
required property var model
|
||||
opacity: model.month == parent.parent.month || model.today ? 1 : 0
|
||||
checked: model.today
|
||||
implicitWidth: root.buttonSize
|
||||
implicitHeight: root.buttonSize
|
||||
radius: height / 2
|
||||
|
||||
required property int index
|
||||
|
||||
contentItem: Item {
|
||||
WText {
|
||||
anchors.centerIn: parent
|
||||
text: monthDayButton.model.day
|
||||
color: {
|
||||
if (monthDayButton.model.today)
|
||||
return Looks.colors.accentFg;
|
||||
if (monthDayButton.model.month == root.currentMonth - 1)
|
||||
return Looks.colors.fg;
|
||||
return Looks.colors.subfg;
|
||||
}
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import qs.modules.waffle.looks
|
||||
|
||||
BodyRectangle {
|
||||
id: root
|
||||
|
||||
// State
|
||||
property bool collapsed
|
||||
|
||||
implicitHeight: collapsed ? 0 : contentColumn.implicitHeight
|
||||
implicitWidth: contentColumn.implicitWidth
|
||||
|
||||
Behavior on implicitHeight {
|
||||
animation: Looks.transition.enter.createObject(this)
|
||||
}
|
||||
|
||||
clip: true
|
||||
ColumnLayout {
|
||||
id: contentColumn
|
||||
spacing: 12
|
||||
CalendarHeader {
|
||||
Layout.topMargin: 10
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 5
|
||||
Layout.rightMargin: 5
|
||||
spacing: 1
|
||||
DayOfWeekRow {
|
||||
Layout.fillWidth: true
|
||||
locale: Qt.locale("en-GB")
|
||||
spacing: calendarView.buttonSpacing
|
||||
implicitHeight: calendarView.buttonSize
|
||||
delegate: Item {
|
||||
id: dayOfWeekItem
|
||||
required property var model
|
||||
implicitHeight: calendarView.buttonSize
|
||||
implicitWidth: calendarView.buttonSize
|
||||
WText {
|
||||
anchors.centerIn: parent
|
||||
text: dayOfWeekItem.model.shortName.substring(0,2)
|
||||
color: Looks.colors.fg
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
}
|
||||
}
|
||||
}
|
||||
CalendarView {
|
||||
id: calendarView
|
||||
verticalPadding: 2
|
||||
buttonSize: 41 // ???
|
||||
buttonSpacing: 1
|
||||
Layout.fillWidth: true
|
||||
delegate: DayButton {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component DayButton: WButton {
|
||||
id: dayButton
|
||||
required property var model
|
||||
checked: model.today
|
||||
enabled: hovered || calendarView.scrolling || checked || model.month === calendarView.focusedMonth
|
||||
implicitWidth: calendarView.buttonSize
|
||||
implicitHeight: calendarView.buttonSize
|
||||
radius: height / 2
|
||||
|
||||
required property int index
|
||||
|
||||
contentItem: Item {
|
||||
WText {
|
||||
anchors.centerIn: parent
|
||||
text: dayButton.model.day
|
||||
color: dayButton.fgColor
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component CalendarHeader: RowLayout {
|
||||
Layout.leftMargin: 8
|
||||
Layout.rightMargin: 8
|
||||
spacing: 8
|
||||
|
||||
WBorderlessButton {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 34
|
||||
contentItem: Item {
|
||||
WText {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: Qt.locale().toString(calendarView.dateInFirstWeek, "MMMM yyyy")
|
||||
font.pixelSize: Looks.font.pixelSize.large
|
||||
font.weight: Looks.font.weight.strong
|
||||
}
|
||||
}
|
||||
}
|
||||
ScrollMonthButton {
|
||||
scrollDown: false
|
||||
}
|
||||
ScrollMonthButton {
|
||||
scrollDown: true
|
||||
}
|
||||
}
|
||||
|
||||
component ScrollMonthButton: WBorderlessButton {
|
||||
id: scrollMonthButton
|
||||
required property bool scrollDown
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
onClicked: {
|
||||
calendarView.scrollMonthsAndSnap(scrollDown ? 1 : -1);
|
||||
}
|
||||
implicitWidth: 32
|
||||
implicitHeight: 34
|
||||
|
||||
contentItem: FluentIcon {
|
||||
filled: true
|
||||
implicitSize: 12
|
||||
icon: scrollMonthButton.scrollDown ? "caret-down" : "caret-up"
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -12,8 +12,12 @@ import qs.modules.waffle.looks
|
||||
FooterRectangle {
|
||||
id: root
|
||||
|
||||
property bool collapsed
|
||||
implicitWidth: 0
|
||||
property bool collapsed
|
||||
color: ColorUtils.transparentize(Looks.colors.bgPanelBody, collapsed ? 0 : 1)
|
||||
Behavior on color {
|
||||
animation: Looks.transition.color.createObject(this)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors {
|
||||
@@ -12,6 +12,7 @@ import qs.modules.waffle.looks
|
||||
FooterRectangle {
|
||||
Layout.fillWidth: true
|
||||
implicitWidth: 0
|
||||
color: Looks.colors.bgPanelBody
|
||||
|
||||
RowLayout {
|
||||
anchors {
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ WBarAttachedPanelContent {
|
||||
WPane {
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
CalendarHeader {
|
||||
DateHeader {
|
||||
Layout.fillWidth: true
|
||||
Synchronizer on collapsed {
|
||||
property alias source: root.collapsed
|
||||
@@ -39,8 +39,8 @@ WBarAttachedPanelContent {
|
||||
|
||||
WPanelSeparator { visible: !root.collapsed }
|
||||
|
||||
CalendarView {
|
||||
// Layout.fillWidth: true
|
||||
CalendarWidget {
|
||||
Layout.fillWidth: true
|
||||
Synchronizer on collapsed {
|
||||
property alias source: root.collapsed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user