ck/Main.go

194 lines
4.2 KiB
Go
Raw Normal View History

2021-07-20 23:22:07 +02:00
package main
import (
"log"
"os"
"strconv"
2021-09-04 11:50:23 +02:00
"time"
2021-07-20 23:22:07 +02:00
"unicode/utf8"
"github.com/gdamore/tcell/v2"
)
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) */
2021-08-27 17:37:38 +02:00
titleHeight = smallGap + 1
2021-07-20 23:22:07 +02:00
)
var (
months = [...]string{"", "Јануар", "Фебруар", "Март", "Април", "Мај", "Јун",
"Јул", "Август", "Септембар", "Октобар", "Новембар", "Децембар"}
weekdays = [...]string{"Недеља", "Понедељак", "Уторак", "Среда", "Четвртак",
"Петак", "Субота"}
)
var (
wall tcell.Screen
defStyle tcell.Style
todayStyle tcell.Style
selStyle tcell.Style
monthsWide int
monthsHigh int
monthsDrawn int
2021-07-20 23:22:07 +02:00
)
var (
selTime time.Time
today time.Time
)
func max(a, b int) int {
if a > b {
return a
}
return b
}
2021-08-25 18:31:01 +02:00
func min(a, b int) int {
if a < b {
return a
}
return b
}
2021-07-20 23:22:07 +02:00
func date(year int, month time.Month, day int) time.Time {
return time.Date(year, month, day, 0, 0, 0, 0, time.Local)
}
func centeredText(s string, x, y, width int, scr tcell.Screen, style tcell.Style) {
2021-09-04 11:50:23 +02:00
start := x + max((width-utf8.RuneCountInString(s))/2, 0)
2021-07-20 23:22:07 +02:00
i := 0
for _, char := range s {
if i >= width {
2021-09-04 11:50:23 +02:00
break
2021-07-20 23:22:07 +02:00
}
2021-09-04 11:50:23 +02:00
scr.SetContent(start+i, y, char, nil, style)
2021-07-20 23:22:07 +02:00
i++
}
}
2021-08-25 18:33:47 +02:00
func wrappedText(s string, scr tcell.Screen, style tcell.Style) {
x := 0
y := 0
w, h := scr.Size()
for _, char := range s {
if x >= w {
if y >= h {
2021-09-04 11:50:23 +02:00
break
2021-08-25 18:33:47 +02:00
}
x = 0
y++
}
scr.SetContent(x, y, char, nil, style)
x++
}
}
2021-07-20 23:22:07 +02:00
func drawMonth(m time.Month, x, y int) {
centeredText(months[m], x, y, maxMonthWidth, wall, defStyle)
2021-07-20 23:22:07 +02:00
for i := 1; i <= 7; i++ {
2021-09-04 11:50:23 +02:00
centeredText(weekdays[i%7], x+(i-1)*(dayWidth+smallGap), y+1, dayWidth, wall, defStyle)
2021-07-20 23:22:07 +02:00
}
2021-09-04 11:50:23 +02:00
dayNum := date(selTime.Year(), m+1, 0).Day()
2021-07-20 23:22:07 +02:00
for i := 1; i <= dayNum; i++ {
weekday := int(date(selTime.Year(), m, i).Weekday())
style := defStyle
if today.Day() == i && today.Month() == m {
style = todayStyle
} else if selTime.Day() == i && selTime.Month() == m {
2021-07-20 23:22:07 +02:00
style = selStyle
}
centeredText(
strconv.Itoa(i),
2021-09-04 11:50:23 +02:00
x+((weekday-1+7)%7)*(dayWidth+smallGap),
y+2,
2021-07-20 23:22:07 +02:00
2,
wall,
style)
if weekday == 0 {
y++
}
}
}
func drawWall() {
2021-08-28 09:39:28 +02:00
wall.Clear()
2021-08-27 17:39:05 +02:00
w, h := wall.Size()
if w < maxMonthWidth+2*smallGap || h < maxMonthHeight+2*smallGap+titleHeight {
2021-08-27 17:39:05 +02:00
wrappedText("Екран је премали за календар.", wall, defStyle)
return
}
monthsWide = (w - 2*smallGap + largeGap) / (maxMonthWidth + largeGap)
monthsHigh = (h - smallGap - titleHeight) / (maxMonthHeight + smallGap)
monthsDrawn = min(monthsHigh*monthsWide, 12)
2021-08-27 17:39:05 +02:00
2021-09-04 11:50:23 +02:00
startingMonth := time.Month((int(selTime.Month())-1)/monthsDrawn*monthsDrawn + 1)
endingMonth := time.Month(min(12, int(startingMonth)+monthsDrawn-1))
2021-08-27 17:39:05 +02:00
centerVert := (w - monthsWide*maxMonthWidth - (monthsWide-1)*largeGap) / 2
2021-09-04 11:50:23 +02:00
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))
2021-08-27 17:39:05 +02:00
if m >= endingMonth {
return
}
m++
}
}
2021-07-20 23:22:07 +02:00
}
func main() {
today = time.Now()
selTime = today
var err error
wall, err = tcell.NewScreen()
if err != nil {
log.Fatalf("%+v", err)
}
if err := wall.Init(); err != nil {
log.Fatalf("%+v", err)
}
defStyle = tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.ColorReset)
todayStyle = tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.GetColor("blue")).Bold(true).Reverse(true)
2021-07-20 23:22:07 +02:00
selStyle = tcell.StyleDefault.Background(tcell.ColorReset).Foreground(tcell.GetColor("green")).Bold(true)
wall.SetStyle(defStyle)
wall.Clear()
2021-08-27 17:39:05 +02:00
drawWall()
2021-07-20 23:22:07 +02:00
quit := func() {
wall.Fini()
os.Exit(0)
}
for {
// Update screen
wall.Show()
// Poll event
ev := wall.PollEvent()
// Process event
switch ev := ev.(type) {
case *tcell.EventResize:
2021-08-28 09:39:28 +02:00
drawWall()
2021-07-20 23:22:07 +02:00
wall.Sync()
case *tcell.EventKey:
if ev.Key() == tcell.KeyEscape || ev.Key() == tcell.KeyCtrlC ||
ev.Rune() == 'Q' || ev.Rune() == 'q' {
quit()
}
}
}
}