164 lines
4.4 KiB
Go
164 lines
4.4 KiB
Go
package main
|
|
|
|
import (
|
|
"math"
|
|
"sync"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
"gitlab.com/tslocum/cview"
|
|
"gitlab.com/tslocum/joker"
|
|
)
|
|
|
|
const (
|
|
cardWidth = 15
|
|
cardHeight = 13
|
|
cardBufferX = 6
|
|
)
|
|
|
|
type cardStackWidget struct {
|
|
*cview.Box
|
|
|
|
Cards []*cardWidget
|
|
EverSelectable bool
|
|
Text string
|
|
|
|
maxSelection int // TODO != 0 unnecessary?
|
|
|
|
sync.RWMutex
|
|
}
|
|
|
|
func newCardStackWidget() *cardStackWidget {
|
|
c := cardStackWidget{Box: cview.NewBox()}
|
|
return &c
|
|
}
|
|
|
|
func (c *cardStackWidget) SetMaxSelection(maxSelection int) {
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
|
|
c.maxSelection = maxSelection
|
|
}
|
|
|
|
func (c *cardStackWidget) GetMaxSelection() int {
|
|
c.RLock()
|
|
defer c.RUnlock()
|
|
|
|
return c.maxSelection
|
|
}
|
|
|
|
func (c *cardStackWidget) SetCards(cards joker.Cards) {
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
|
|
current := make(joker.Cards, len(c.Cards))
|
|
for i := range c.Cards {
|
|
current[i] = c.Cards[i].Card
|
|
}
|
|
if current.Equal(cards) {
|
|
return
|
|
}
|
|
|
|
c.Cards = make([]*cardWidget, len(cards))
|
|
for i := 0; i < len(cards); i++ {
|
|
c.Cards[i] = newCardWidget(cards[i], throwCard)
|
|
}
|
|
}
|
|
|
|
func (c *cardStackWidget) Draw(screen tcell.Screen) {
|
|
c.Box.Draw(screen)
|
|
|
|
c.RLock()
|
|
defer c.RUnlock()
|
|
|
|
cardOffsetY := 1
|
|
lastOffsetY := 1
|
|
if !c.EverSelectable {
|
|
cardOffsetY = 0
|
|
lastOffsetY = 0
|
|
}
|
|
|
|
stackX, stackY, _, _ := c.GetInnerRect()
|
|
for i, cardWidget := range c.Cards {
|
|
lastOffsetY = cardOffsetY
|
|
|
|
cardOffsetY = 1
|
|
if c.Cards[i].selected || !c.EverSelectable {
|
|
cardOffsetY = 0
|
|
}
|
|
|
|
cardWidget.SetRect(stackX+(i*cardBufferX), stackY+cardOffsetY, cardWidth, cardHeight)
|
|
cardWidget.Draw(screen)
|
|
|
|
// Fix borders
|
|
if i > 0 && cardOffsetY == lastOffsetY {
|
|
screen.SetContent(stackX+(i*cardBufferX), stackY+cardOffsetY, tcell.RuneTTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && (cardOffsetY == lastOffsetY) {
|
|
screen.SetContent(stackX+(i*cardBufferX), (stackY+cardOffsetY+cardHeight)-1, tcell.RuneBTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && !cardWidget.selected && c.Cards[i-1].selected {
|
|
screen.SetContent(stackX+(i*cardBufferX), (stackY+cardOffsetY+cardHeight)-2, tcell.RuneRTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && cardWidget.selected && !c.Cards[i-1].selected {
|
|
screen.SetContent(stackX+(i*cardBufferX), stackY+cardOffsetY+1, tcell.RuneRTee, nil, tcell.StyleDefault)
|
|
screen.SetContent(stackX+(i*cardBufferX)+(cardBufferX)+2, (stackY+cardOffsetY+cardHeight)-1, tcell.RuneTTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && (i > 1 && !cardWidget.selected && c.Cards[i-1].selected && !c.Cards[i-2].selected) {
|
|
screen.SetContent(stackX+(i*cardBufferX), (stackY+cardOffsetY+cardHeight)-1, tcell.RuneBTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && (i > 1 && cardWidget.selected && c.Cards[i-1].selected && !c.Cards[i-2].selected) {
|
|
screen.SetContent(stackX+(i*cardBufferX)+2, (stackY+cardOffsetY+cardHeight)-1, tcell.RuneTTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && (i > 1 && cardWidget.selected && !c.Cards[i-1].selected && c.Cards[i-2].selected) {
|
|
screen.SetContent(stackX+(i*cardBufferX), stackY+cardOffsetY, tcell.RuneTTee, nil, tcell.StyleDefault)
|
|
}
|
|
|
|
if i > 0 && (i > 1 && !cardWidget.selected && !c.Cards[i-1].selected && c.Cards[i-2].selected) {
|
|
screen.SetContent(stackX+(i*cardBufferX)+2, stackY+cardOffsetY, tcell.RuneBTee, nil, tcell.StyleDefault)
|
|
}
|
|
}
|
|
|
|
if c.Text != "" && len(c.Cards) > 0 {
|
|
cview.Print(screen, c.Text, (stackX+((len(c.Cards)-1)*cardBufferX))+(cardWidth/2), stackY, math.MaxInt64, cview.AlignLeft, tcell.ColorDefault)
|
|
cview.Print(screen, c.Text, (stackX+((len(c.Cards)-1)*cardBufferX))+(cardWidth/2), (stackY+cardHeight)-1, math.MaxInt64, cview.AlignLeft, tcell.ColorDefault)
|
|
}
|
|
}
|
|
|
|
// MouseHandler returns the mouse handler for this primitive.
|
|
func (c *cardStackWidget) MouseHandler() func(action cview.MouseAction, event *tcell.EventMouse, setFocus func(p cview.Primitive)) (consumed bool, capture cview.Primitive) {
|
|
return c.WrapMouseHandler(func(action cview.MouseAction, event *tcell.EventMouse, setFocus func(p cview.Primitive)) (consumed bool, capture cview.Primitive) {
|
|
if !c.InRect(event.Position()) {
|
|
return false, nil
|
|
}
|
|
|
|
c.Lock()
|
|
defer c.Unlock()
|
|
|
|
for i := range c.Cards {
|
|
card := c.Cards[(len(c.Cards)-1)-i]
|
|
if card.InRect(event.Position()) {
|
|
if !card.selected {
|
|
selected := 0
|
|
for i := range c.Cards {
|
|
if c.Cards[i].selected {
|
|
selected++
|
|
}
|
|
}
|
|
if selected >= c.maxSelection {
|
|
return // TODO Show error
|
|
}
|
|
}
|
|
|
|
return card.MouseHandler()(action, event, setFocus)
|
|
}
|
|
}
|
|
|
|
return
|
|
})
|
|
}
|