![Petar Kapriš](/assets/img/avatar_default.png)
Until this commit there was a bug which caused the current selected year to change if the user 'L'-ed past the right of December, while the number of months which can fit into one row did not divide 12.
193 lines
4.7 KiB
Go
193 lines
4.7 KiB
Go
package drw
|
||
|
||
import (
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/gdamore/tcell/v2"
|
||
|
||
"gitlab.com/tvrdosrz/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 (
|
||
Wall tcell.Screen
|
||
|
||
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 {
|
||
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()) <= (12-1)/monthsWide*monthsWide {
|
||
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 && int(util.SelTime.Month()) != 12 {
|
||
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(m time.Month, x, y int) {
|
||
centeredText(months[m], x, y, maxMonthWidth, Wall, DefStyle)
|
||
|
||
for i := 1; i <= 7; i++ {
|
||
centeredText(weekdays[i%7], x+(i-1)*(dayWidth+smallGap), y+1, dayWidth, Wall, DefStyle)
|
||
}
|
||
|
||
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())
|
||
style := DefStyle
|
||
if util.Today.Day() == i && util.Today.Month() == m {
|
||
style = TodayStyle
|
||
} else if util.SelTime.Day() == i && util.SelTime.Month() == m {
|
||
style = SelStyle
|
||
}
|
||
centeredText(
|
||
strconv.Itoa(i),
|
||
x+((weekday-1+7)%7)*(dayWidth+smallGap),
|
||
y+2,
|
||
2,
|
||
Wall,
|
||
style)
|
||
if weekday == 0 {
|
||
y++
|
||
}
|
||
}
|
||
}
|
||
|
||
func DrawWall() {
|
||
Wall.Clear()
|
||
w, h := Wall.Size()
|
||
if w < maxMonthWidth+2*smallGap || h < maxMonthHeight+2*smallGap+titleHeight {
|
||
wrappedText("Екран је премали за календар.", Wall, DefStyle)
|
||
return
|
||
}
|
||
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(m, centerVert+j*(maxMonthWidth+largeGap), titleHeight+smallGap+i*(maxMonthHeight+smallGap))
|
||
if m >= endingMonth {
|
||
return
|
||
}
|
||
m++
|
||
}
|
||
}
|
||
}
|