You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.4 KiB
164 lines
4.4 KiB
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 |
|
}) |
|
}
|
|
|