ck/drw/wall.go
2025-08-08 11:04:49 +02:00

209 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package drw
import (
"strconv"
"time"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"git.bonsai.cool/kayprish/ck/util"
)
const (
dayWidth = 2
smallGap = 1
largeGap = 3
maxMonthWidth = 7*dayWidth + 6*smallGap
maxMonthHeight = (31+6+(7-1))/7 + 2
/* maxMonthHeight is the height of a 31-day month starting on Sunday (month
name and weekdays included) */
titleHeight = smallGap + 1
)
var (
monthsWide int
monthsHigh int
monthsDrawn int
)
func offset(m time.Month) int {
return (int(util.Date(util.SelTime.Year(), m, 1).Weekday()) + 6) % 7
}
func lastDay(m time.Month) time.Time {
return util.Date(util.SelTime.Year(), m+1, 0)
}
func monthHeight(m time.Month) int {
return (offset(m) + lastDay(m).Day() - 1) / 7
}
func bottomOfMonth(m time.Month, w time.Weekday) (time time.Time) {
last := lastDay(m)
day := last.Day()
if w > last.Weekday() {
day -= 7
}
day += int(w - last.Weekday())
time = util.Date(util.SelTime.Year(), m, day)
return
}
func topOfMonth(m time.Month, w time.Weekday) (time time.Time) {
first := util.Date(util.SelTime.Year(), m, 1)
day := 1
if w < first.Weekday() {
day += 7
}
day += int(w - first.Weekday())
time = util.Date(util.SelTime.Year(), m, day)
return
}
func rowInMonth(m time.Month, day int) int {
return (day + offset(m) - 1) / 7
}
func leftmostInRow(m time.Month, row int) time.Time {
if row == 0 {
return util.Date(util.SelTime.Year(), m, 1)
}
if row > monthHeight(m) {
row = monthHeight(m)
}
day := row*7 + 1 - offset(m)
return util.Date(util.SelTime.Year(), m, day)
}
func rightmostInRow(m time.Month, row int) time.Time {
if row >= monthHeight(m) {
return lastDay(m)
}
day := row*7 + 7 - offset(m)
return util.Date(util.SelTime.Year(), m, day)
}
func MoveUp() {
weekday := util.SelTime.Weekday()
newTime := util.SelTime.AddDate(0, 0, -7)
if newTime.Month() == util.SelTime.Month() {
util.SelTime = newTime
} else if int(util.SelTime.Month())-monthsWide >= 1 {
newMonth := util.SelTime.Month() - time.Month(monthsWide)
util.SelTime = bottomOfMonth(newMonth, weekday)
}
}
func MoveDown() {
weekday := util.SelTime.Weekday()
newTime := util.SelTime.AddDate(0, 0, +7)
if newTime.Month() == util.SelTime.Month() {
util.SelTime = newTime
} else if int(util.SelTime.Month())+monthsWide <= 12 {
newMonth := util.SelTime.Month() + time.Month(monthsWide)
util.SelTime = topOfMonth(newMonth, weekday)
}
}
func MoveRight() {
if util.SelTime.Weekday() != time.Sunday && util.SelTime.Day() != lastDay(util.SelTime.Month()).Day() {
util.SelTime = util.SelTime.AddDate(0, 0, 1)
} else if int(util.SelTime.Month())%monthsWide != 0 && util.SelTime.Month() != time.December {
util.SelTime = leftmostInRow(util.SelTime.Month()+1, rowInMonth(util.SelTime.Month(), util.SelTime.Day()))
}
}
func MoveLeft() {
if util.SelTime.Weekday() != time.Monday && util.SelTime.Day() != 1 {
util.SelTime = util.SelTime.AddDate(0, 0, -1)
} else if int(util.SelTime.Month())%monthsWide != 1 && monthsWide != 1 { // special case, if monthsWide
// is 1, (x%monthsWide) is 0
util.SelTime = rightmostInRow(util.SelTime.Month()-1, rowInMonth(util.SelTime.Month(), util.SelTime.Day()))
}
}
func drawMonth(screen tcell.Screen, m time.Month, x, y int) {
tview.Print(screen, months[m], x, y, maxMonthWidth, tview.AlignCenter, tcell.ColorWhite)
for i := 1; i <= 7; i++ {
tview.Print(screen, weekdays[i%7], x+(i-1)*(dayWidth+smallGap), y+1, dayWidth, tview.AlignLeft, tcell.ColorWhite)
}
dayNum := util.Date(util.SelTime.Year(), m+1, 0).Day()
for i := 1; i <= dayNum; i++ {
weekday := int(util.Date(util.SelTime.Year(), m, i).Weekday())
dayText := strconv.Itoa(i)
if util.Today.Day() == i && util.Today.Month() == m {
dayText = "[blue]" + dayText
} else if util.SelTime.Day() == i && util.SelTime.Month() == m {
dayText = "[green]" + dayText
}
tview.Print(
screen,
dayText,
x+((weekday-1+7)%7)*(dayWidth+smallGap),
y+2,
2,
tview.AlignRight,
tcell.ColorWhite)
if weekday == 0 {
y++
}
}
}
func DrawWall(screen tcell.Screen, x int, y int, w int, h int) (int, int, int, int) {
x += 1
y += 1
w -= 2
h -= 2 // We'll do calculations based on the inside of the box
if w < maxMonthWidth+2*smallGap || h < maxMonthHeight+2*smallGap+titleHeight {
tview.Print(screen, "Екран је премали за календар.", x, y, w, tview.AlignCenter, tcell.ColorRed) // The screen is too small for the calender
return 0, 0, 0, 0
}
monthsWide = (w - 2*smallGap + largeGap) / (maxMonthWidth + largeGap)
monthsHigh = (h - smallGap - titleHeight) / (maxMonthHeight + smallGap)
monthsDrawn = util.Min(monthsHigh*monthsWide, 12)
startingMonth := time.Month((int(util.SelTime.Month())-1)/monthsDrawn*monthsDrawn + 1)
endingMonth := time.Month(util.Min(12, int(startingMonth)+monthsDrawn-1))
centerVert := (w - monthsWide*maxMonthWidth - (monthsWide-1)*largeGap) / 2
for i, m := 0, startingMonth; i < monthsHigh; i++ {
for j := 0; j < monthsWide; j++ {
drawMonth(screen, m, x+centerVert+j*(maxMonthWidth+largeGap), y+titleHeight+smallGap+i*(maxMonthHeight+smallGap))
if m >= endingMonth {
return 0, 0, 0, 0
}
m++
}
}
return 0, 0, 0, 0
}
func WallInputCapture(ev *tcell.EventKey) *tcell.EventKey {
switch ev.Rune() {
case 'h':
MoveLeft()
case 'j':
MoveDown()
case 'k':
MoveUp()
case 'l':
MoveRight()
}
return nil
}