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 }