mirai/src/components/Calendar.slint

169 lines
4.1 KiB
Text

import { ScrollView, Date, Time } from "std-widgets.slint";
import { VCheckBox, VButton, VActionButton, Svg, VTag, VPopupIconMenu, VText, Palette } from "@selenite";
import { Utils } from "../shared/Utils.slint";
export struct CalendarDayEvent {
sourceId: int,
id: int,
title: string,
startsAt: Time,
endsAt: Time
}
export struct CalendarDay {
events: [CalendarDayEvent],
date: Date,
header: string,
}
export enum CalendarDateDisplayFormat {
Relative,
Normal
}
export component Calendar inherits Rectangle {
in property<[CalendarDay]> days;
in property <CalendarDateDisplayFormat> format;
in property <Date> current-date;
in property <Time> current-time;
private property <length> header-height: 64px;
private property <length> available-day-space: self.height - header-height;
private property <length> day-start-y: header-height;
private property <length> hour-spacing: available-day-space / 24;
private property <int> contextMenuEventSourceId: -1;
callback delete-event-request(source-id: int, event-id: int);
HorizontalLayout {
Rectangle {
//background: red;
width: 48px;
VerticalLayout {
y: 0;
height: header-height;
padding-right: 8px;
VText {
vertical-alignment: center;
horizontal-alignment: right;
text: "";
}
}
for index in 24: VerticalLayout {
y: day-start-y + index * hour-spacing - (hour-spacing / 2);
height: hour-spacing;
padding-right: 8px;
VText {
vertical-alignment: center;
horizontal-alignment: right;
text: "\{index}";
}
}
}
Rectangle {
Rectangle {
x: parent.width - 1px;
y: header-height - 32px;
width: 1px;
height: parent.height - self.y;
background: Palette.card-background.brighter(0.3);
}
min-width: 400px;
//background: green;
HorizontalLayout {
for day[day-index] in root.days: Rectangle {
Rectangle {
x: 0;
y: header-height - 32px;
width: 1px;
height: parent.height - self.y;
background: Palette.card-background.brighter(0.3);
}
VerticalLayout {
y: 0;
height: header-height;
padding-right: 8px;
VText {
vertical-alignment: center;
horizontal-alignment: center;
text: day.header;
}
}
for hour[hour-index] in 24 : Rectangle {
background: Palette.card-background.brighter(0.3);
x: 0px;
width: parent.width;
y: day-start-y + hour-spacing * hour-index;
height: 1px;
}
if day.date == root.current-date : Rectangle {
background: Palette.red;
x: 0px;
width: parent.width;
y: day-start-y + hour-spacing * root.current-time.hour + (root.current-time.minute / 60 * hour-spacing);
height: 1px;
}
for event[event-index] in day.events : Rectangle {
background: Palette.card-background;
border-radius: 4px;
x: 8px;
width: parent.width - 16px;
y: day-start-y + hour-spacing * event.startsAt.hour;
height: hour-spacing * (event.endsAt.hour - event.startsAt.hour) - 2px;
clip: true;
HorizontalLayout {
Rectangle {
width: 4px;
background: Palette.accent;
}
VerticalLayout {
padding: 16px;
VText {
text: event.title;
wrap: TextWrap.word-wrap;
}
}
}
eventActionsPopup := VPopupIconMenu {
//VActionButton {
//icon-svg: Svg.pen;
//icon-colorize: Colors.grey;
//icon-size: 1.5rem;
//border-radius: 0;
//clicked => {
//taskEdit.show({
//title: title,
//date: date
//});
//}
//}
VActionButton {
icon-svg: Svg.trash;
icon-colorize: Colors.pink;
icon-size: 1.5rem;
border-radius: 0;
clicked => {
delete-event-request(event.sourceId, event.id);
}
}
}
ta := TouchArea {
pointer-event(e) => {
if (e.button == PointerEventButton.right && e.kind == PointerEventKind.up) {
eventActionsPopup.show(ta.mouse-x, ta.mouse-y);
}
}
}
}
}
}
}
}
}