1
0
Fork 0
tetris-go/game/ui/widgets/slider.go

136 lines
3.1 KiB
Go

package widgets
import (
"fmt"
"image/color"
"tetris/engine/core"
"tetris/engine/input"
"tetris/engine/render"
"tetris/game/ui/base"
rl "github.com/gen2brain/raylib-go/raylib"
)
const (
sliderBorderSize = 4
sliderWidth = 200
sliderHeight = 30
sliderTextSize = 12
sliderTextOffset = 6
)
type SliderOnChange func(this *Slider)
type Slider struct {
*base.WithFocus
Min int
Max int
Step int
Value int
borderSize int32
onChange SliderOnChange
}
func NewSlider(min, max, step int) *Slider {
return &Slider{
WithFocus: &base.WithFocus{},
Min: min,
Max: max,
Step: step,
borderSize: 4,
}
}
func (slider *Slider) WithOnChange(callback SliderOnChange) *Slider {
slider.onChange = callback
return slider
}
func (slider Slider) Size() core.Vec2i {
w := sliderWidth + (sliderBorderSize * 2)
return core.Vec2i{
X: w + sliderTextOffset + (sliderTextSize * len(slider.ValueText())),
Y: sliderHeight + (sliderBorderSize * 2),
}
}
func (slider *Slider) HandleInput() {
if input.KeyPressedWithRepeat(rl.KeyLeft) {
slider.Decrement()
} else if input.KeyPressedWithRepeat(rl.KeyRight) {
slider.Increment()
}
}
func (slider *Slider) SetValue(value int) {
if value != slider.Value {
slider.Value = value
slider.onChange(slider)
}
}
func (slider *Slider) Increment() {
slider.SetValue(min(slider.Max, slider.Value+slider.Step))
}
func (slider *Slider) Decrement() {
slider.SetValue(max(slider.Min, slider.Value-slider.Step))
}
func (slider Slider) Percent() float32 {
return float32(slider.Min+slider.Value) / float32(slider.Max)
}
func (slider Slider) drawTrack(rect rl.RectangleInt32) {
spacing := int32(2)
num_marks := int32(10)
mark_width := float32(rect.Width-((num_marks+1)*spacing)) / float32(num_marks)
markRect := rl.Rectangle{
X: float32(rect.X + spacing),
Y: float32(rect.Y + spacing),
Width: mark_width,
Height: float32(rect.Height - (spacing * 2)),
}
for range num_marks {
rl.DrawRectangleRec(markRect, rl.DarkGray)
markRect.X += mark_width + float32(spacing)
}
}
func (slider Slider) drawHandle(x, y, width int32, height int32, col color.RGBA) {
handleWidth := int32(10)
x = x + int32(float32(width-handleWidth-2)*slider.Percent())
rl.DrawRectangle(x, y, handleWidth, height, col)
}
func (slider Slider) ValueText() string {
return fmt.Sprintf("%d", int(slider.Percent()*100))
}
func (slider Slider) Draw(x, y int32) {
// rl.DrawRectangle(x, y, int32(slider.Size().X), int32(slider.Size().Y), rl.Green)
// TODO: use a theme system here so colors are not hardcoded.
handleColor := rl.White
if slider.HasFocus() {
handleColor = rl.Red
}
rect := rl.RectangleInt32{
X: x + sliderBorderSize,
Y: y + sliderBorderSize,
Width: sliderWidth,
Height: sliderHeight,
}
render.DrawRectOutlineBorder(rect, slider.borderSize, handleColor)
slider.drawTrack(rect)
slider.drawHandle(rect.X+1, rect.Y+1, int32(rect.Width), sliderHeight-2, handleColor)
textOffset := x + int32(rect.Width) + (sliderBorderSize * 2) + sliderTextOffset
render.DrawText(textOffset, rect.Y+8, sliderTextSize, slider.ValueText(), rl.White)
}