Compare commits

...

8 Commits

Author SHA1 Message Date
102c187566 Added generic margin. 2020-12-13 07:43:00 +01:00
11e37af9c2 Added shorthand method for retrieving default font for the control. 2020-12-13 07:40:58 +01:00
5babda0ca9 Added (optional) dropshadow for label. 2020-12-13 07:40:58 +01:00
b1cdbea90f Changed colors of button text a bit. 2020-12-13 07:40:58 +01:00
7d5168614e Added override for scrollbar color. 2020-12-13 07:40:58 +01:00
b0a13d1a3c ContainerBase now provides a DesiredSize (maximum of all children, if any). 2020-12-13 07:40:58 +01:00
cc32cf5bc3 Added scaled ImageSource. 2020-12-13 07:40:58 +01:00
0f03760e66 Added Resize & SetIcon to Renderer.
Refactored Size (on Renderer) to return geom.Point instead of geom.PointF32.
Refactored Width and Height (on Texture) to return int instead of float32.

Refactored texture dimensions to be represented by ints instead of float32s.
2020-12-13 07:40:19 +01:00
20 changed files with 190 additions and 80 deletions

View File

@ -180,7 +180,7 @@ func (r *Renderer) CreateFontPath(path string, size int) (ui.Font, error) {
return &font{f}, nil return &font{f}, nil
} }
func (r *Renderer) createTexture(source ui.ImageSource, keepSource bool) (ui.Texture, error) { func (r *Renderer) createTexture(source ui.ImageSource, keepSource bool) (*texture, error) {
im, err := source.CreateImage() im, err := source.CreateImage()
if err != nil { if err != nil {
return nil, err return nil, err
@ -314,15 +314,23 @@ func (r *Renderer) RenderToDisplay() {
r.disp.SetAsTarget() r.disp.SetAsTarget()
} }
func (r *Renderer) Resources() ui.Resources { return r.res } func (r *Renderer) Resize(width, height int) {
r.disp.Resize(width, height)
func (r *Renderer) Size() geom.PointF32 {
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
} }
func (r *Renderer) SetIcon(texture ui.Texture) { func (r *Renderer) Resources() ui.Resources { return r.res }
bmp := r.mustGetBitmap(texture)
r.disp.SetIcon(bmp) func (r *Renderer) Size() geom.Point {
return geom.Pt(r.disp.Width(), r.disp.Height())
}
func (r *Renderer) SetIcon(source ui.ImageSource) {
texture, err := r.createTexture(source, false)
if err != nil {
return
}
defer texture.Destroy()
r.disp.SetIcon(texture.bmp)
} }
func (r *Renderer) SetMouseCursor(c ui.MouseCursor) { func (r *Renderer) SetMouseCursor(c ui.MouseCursor) {

View File

@ -20,8 +20,8 @@ func (t *texture) Destroy() error {
return nil return nil
} }
func (t *texture) Height() float32 { func (t *texture) Height() int {
return float32(t.bmp.Height()) return t.bmp.Height()
} }
func (t *texture) CreateImage() (image.Image, error) { func (t *texture) CreateImage() (image.Image, error) {
@ -31,6 +31,6 @@ func (t *texture) CreateImage() (image.Image, error) {
return t.source.CreateImage() return t.source.CreateImage()
} }
func (t *texture) Width() float32 { func (t *texture) Width() int {
return float32(t.bmp.Width()) return t.bmp.Width()
} }

View File

@ -238,7 +238,7 @@ func (r *Renderer) CreateFontPath(path string, size int) (ui.Font, error) {
return &Font{font}, nil return &Font{font}, nil
} }
func (r *Renderer) createTexture(source ui.ImageSource, keepSource bool) (ui.Texture, error) { func (r *Renderer) createSurface(source ui.ImageSource) (*sdl.Surface, error) {
m, err := source.CreateImage() m, err := source.CreateImage()
if err != nil { if err != nil {
return nil, err return nil, err
@ -252,6 +252,14 @@ func (r *Renderer) createTexture(source ui.ImageSource, keepSource bool) (ui.Tex
if err != nil { if err != nil {
return nil, err return nil, err
} }
return surface, nil
}
func (r *Renderer) createTexture(source ui.ImageSource, keepSource bool) (ui.Texture, error) {
surface, err := r.createSurface(source)
if err != nil {
return nil, err
}
defer surface.Free() defer surface.Free()
texture, err := r.renderer.CreateTextureFromSurface(surface) texture, err := r.renderer.CreateTextureFromSurface(surface)
if err != nil { if err != nil {
@ -391,6 +399,10 @@ func (r *Renderer) RenderToDisplay() {
r.renderer.SetRenderTarget(nil) r.renderer.SetRenderTarget(nil)
} }
func (r *Renderer) Resize(width, height int) {
r.window.SetSize(int32(width), int32(height))
}
func (r *Renderer) SetDrawColor(c sdl.Color) { func (r *Renderer) SetDrawColor(c sdl.Color) {
r.renderer.SetDrawColor(c.R, c.G, c.B, c.A) r.renderer.SetDrawColor(c.R, c.G, c.B, c.A)
} }
@ -399,14 +411,27 @@ func (r *Renderer) SetDrawColorGo(c color.Color) {
r.SetDrawColor(ColorSDL(c)) r.SetDrawColor(ColorSDL(c))
} }
func (r *Renderer) SetIcon(source ui.ImageSource) {
window := r.window
if window == nil {
return
}
surface, err := r.createSurface(source)
if err != nil {
return
}
defer surface.Free()
window.SetIcon(surface)
}
func (r *Renderer) SetMouseCursor(c ui.MouseCursor) { r.cursor = c } func (r *Renderer) SetMouseCursor(c ui.MouseCursor) { r.cursor = c }
func (r *Renderer) Size() geom.PointF32 { func (r *Renderer) Size() geom.Point {
w, h, err := r.renderer.GetOutputSize() w, h, err := r.renderer.GetOutputSize()
if err != nil { if err != nil {
return geom.PtF32(geom.NaN32(), geom.NaN32()) return geom.ZeroPt
} }
return geom.PtF32(float32(w), float32(h)) return geom.Pt(int(w), int(h))
} }
func (r *Renderer) SystemCursor(id sdl.SystemCursor) *sdl.Cursor { func (r *Renderer) SystemCursor(id sdl.SystemCursor) *sdl.Cursor {
@ -493,6 +518,6 @@ func (r *Renderer) SetResourceProvider(resources ui.Resources) {
func (r *Renderer) Image() image.Image { return nil } func (r *Renderer) Image() image.Image { return nil }
func (r *Renderer) Height() float32 { return r.Size().Y } func (r *Renderer) Height() int { return r.Size().Y }
func (r *Renderer) Width() float32 { return r.Size().X } func (r *Renderer) Width() int { return r.Size().X }

View File

@ -5,7 +5,6 @@ import (
"image/color" "image/color"
"github.com/veandco/go-sdl2/sdl" "github.com/veandco/go-sdl2/sdl"
"opslag.de/schobers/geom"
"opslag.de/schobers/zntg/ui" "opslag.de/schobers/zntg/ui"
) )
@ -21,12 +20,12 @@ type Texture struct {
var _ ui.Texture = &Texture{} var _ ui.Texture = &Texture{}
func (t *Texture) Height() float32 { func (t *Texture) Height() int {
_, _, _, height, err := t.Texture.Query() _, _, _, height, err := t.Texture.Query()
if err != nil { if err != nil {
return geom.NaN32() return -1
} }
return float32(height) return int(height)
} }
func (t *Texture) Native() *sdl.Texture { return t.Texture } func (t *Texture) Native() *sdl.Texture { return t.Texture }
@ -44,12 +43,12 @@ func (t *Texture) Size() (int32, int32, error) {
return width, height, err return width, height, err
} }
func (t *Texture) Width() float32 { func (t *Texture) Width() int {
_, _, width, _, err := t.Texture.Query() _, _, width, _, err := t.Texture.Query()
if err != nil { if err != nil {
return geom.NaN32() return -1
} }
return float32(width) return int(width)
} }
var _ ui.ImageSource = &TextureImageSource{} var _ ui.ImageSource = &TextureImageSource{}

View File

@ -41,7 +41,7 @@ func BuildIconButton(icon, text string, fn func(b *Button)) *Button {
func (b *Button) desiredSize(ctx Context) geom.PointF32 { func (b *Button) desiredSize(ctx Context) geom.PointF32 {
var pad = ctx.Style().Dimensions.TextPadding var pad = ctx.Style().Dimensions.TextPadding
var font = ctx.Fonts().Font(b.FontName(ctx)) var font = b.Font_(ctx)
var w, h float32 = 0, font.Height() var w, h float32 = 0, font.Height()
icon, iconW, iconH := b.icon(ctx) icon, iconW, iconH := b.icon(ctx)
@ -71,7 +71,7 @@ func (b *Button) icon(ctx Context) (Texture, float32, float32) {
return nil, 0, 0 return nil, 0, 0
} }
icon := ctx.Textures().Texture(b.Icon) icon := ctx.Textures().Texture(b.Icon)
iconW, iconH := icon.Width(), icon.Height() iconW, iconH := float32(icon.Width()), float32(icon.Height())
if b.IconHeight != 0 { if b.IconHeight != 0 {
iconW = b.IconHeight * iconW / iconH iconW = b.IconHeight * iconW / iconH
iconH = b.IconHeight iconH = b.IconHeight
@ -155,6 +155,13 @@ func (b *Button) fillColor(p *Palette) color.Color {
return nil return nil
} }
func (b *Button) fontColor(c color.Color) color.Color {
if b.Font.Color == nil {
return c
}
return b.Font.Color
}
func (b *Button) textColor(p *Palette) color.Color { func (b *Button) textColor(p *Palette) color.Color {
if b.Disabled { if b.Disabled {
if b.Background != nil { if b.Background != nil {
@ -166,22 +173,19 @@ func (b *Button) textColor(p *Palette) color.Color {
} }
return b.disabledColor(p) return b.disabledColor(p)
} }
if b.Font.Color != nil {
return b.Font.Color
}
switch b.Type { switch b.Type {
case ButtonTypeContained: case ButtonTypeContained:
return p.TextOnPrimary return b.fontColor(p.TextOnPrimary)
case ButtonTypeIcon: case ButtonTypeIcon:
if b.over { if b.over {
if b.HoverColor != nil { if b.HoverColor != nil {
return b.HoverColor return b.HoverColor
} }
return p.Primary return b.fontColor(p.Primary)
} }
return p.Text return b.fontColor(p.Text)
default: default:
return p.Primary return b.fontColor(p.Primary)
} }
} }
@ -213,7 +217,7 @@ func (b *Button) Render(ctx Context) {
if scaled != nil { // let the renderer scale if scaled != nil { // let the renderer scale
icon = scaled icon = scaled
} }
_, iconW = ScaleToHeight(SizeOfTexture(icon), iconH) _, iconW = ScaleToHeight(SizeOfTexture(icon).ToF32(), iconH)
} }
iconOffsetY = .5 * (boundsH - iconH) iconOffsetY = .5 * (boundsH - iconH)
} }
@ -221,8 +225,7 @@ func (b *Button) Render(ctx Context) {
pos.X += iconW + pad pos.X += iconW + pad
} }
if len(b.Text) != 0 { if len(b.Text) != 0 {
fontName := b.FontName(ctx) font := b.Font_(ctx)
font := ctx.Fonts().Font(fontName)
ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), textColor, b.Text) ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), textColor, b.Text)
} }

View File

@ -23,13 +23,13 @@ func BuildCheckbox(text string, fn func(c *Checkbox)) *Checkbox {
func (c *Checkbox) desiredSize(ctx Context) geom.PointF32 { func (c *Checkbox) desiredSize(ctx Context) geom.PointF32 {
var pad = ctx.Style().Dimensions.TextPadding var pad = ctx.Style().Dimensions.TextPadding
var font = ctx.Fonts().Font(c.FontName(ctx)) font := c.Font_(ctx)
var w, h float32 = 0, font.Height() var w, h float32 = 0, font.Height()
if len(c.Text) != 0 { if len(c.Text) != 0 {
w += pad + font.WidthOf(c.Text) w += pad + font.WidthOf(c.Text)
} }
icon := c.getOrCreateNormalIcon(ctx) icon := c.getOrCreateNormalIcon(ctx)
_, iconWidth := ScaleToHeight(SizeOfTexture(icon), h) _, iconWidth := ScaleToHeight(SizeOfTexture(icon).ToF32(), h)
w += pad + iconWidth w += pad + iconWidth
return geom.PtF32(w+pad, pad+h+pad) return geom.PtF32(w+pad, pad+h+pad)
} }
@ -122,14 +122,13 @@ func (c *Checkbox) Render(ctx Context) {
if scaledIcon == nil { // let the renderer scale if scaledIcon == nil { // let the renderer scale
scaledIcon = icon scaledIcon = icon
} }
_, iconWidth := ScaleToHeight(SizeOfTexture(scaledIcon), boundsH) _, iconWidth := ScaleToHeight(SizeOfTexture(scaledIcon).ToF32(), boundsH)
rect := geom.RectRelF32(pos.X, pos.Y, iconWidth, boundsH) rect := geom.RectRelF32(pos.X, pos.Y, iconWidth, boundsH)
ctx.Renderer().DrawTextureOptions(scaledIcon, rect, DrawOptions{Tint: iconColor}) ctx.Renderer().DrawTextureOptions(scaledIcon, rect, DrawOptions{Tint: iconColor})
pos.X += iconWidth + pad pos.X += iconWidth + pad
} }
if len(c.Text) != 0 { if len(c.Text) != 0 {
var fontName = c.FontName(ctx) font := c.Font_(ctx)
var font = ctx.Fonts().Font(fontName)
ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), fore, c.Text) ctx.Renderer().Text(font, geom.PtF32(pos.X, pos.Y+.5*(boundsH-font.Height())), fore, c.Text)
} }
} }

View File

@ -26,6 +26,15 @@ func (c *ContainerBase) Arrange(ctx Context, bounds geom.RectangleF32, offset ge
c.ControlBase.Arrange(ctx, bounds, offset, parent) c.ControlBase.Arrange(ctx, bounds, offset, parent)
} }
func (c *ContainerBase) DesiredSize(ctx Context, size geom.PointF32) geom.PointF32 {
var max geom.PointF32
for _, child := range c.Children {
s := child.DesiredSize(ctx, size)
max = geom.MaxPtF32(max, s)
}
return max
}
func (c *ContainerBase) Handle(ctx Context, e Event) bool { func (c *ContainerBase) Handle(ctx Context, e Event) bool {
if c.ControlBase.Handle(ctx, e) { if c.ControlBase.Handle(ctx, e) {
return true return true

View File

@ -188,6 +188,11 @@ func (c *ControlBase) HandleNotify(ctx Context, e Event, notifier Notifier) bool
return false return false
} }
func (c *ControlBase) Font_(ctx Context) Font {
name := c.FontName(ctx)
return ctx.Fonts().Font(name)
}
func (c *ControlBase) FontColor(ctx Context, color color.Color) color.Color { func (c *ControlBase) FontColor(ctx Context, color color.Color) color.Color {
if c.Disabled { if c.Disabled {
return ctx.Style().Palette.TextOnDisabled return ctx.Style().Palette.TextOnDisabled

View File

@ -91,16 +91,18 @@ func (o *debugOverlay) renderControl(ctx Context, control Control) {
return return
} }
defer nameTexture.Destroy() defer nameTexture.Destroy()
renderer.FillRectangle(pos.RectRel2D(nameTexture.Width(), nameTexture.Height()), color.Black) nameTextureWidth := float32(nameTexture.Width())
nameTextureHeight := float32(nameTexture.Height())
renderer.FillRectangle(pos.RectRel2D(nameTextureWidth, nameTextureHeight), color.Black)
renderer.DrawTexturePoint(nameTexture, pos) renderer.DrawTexturePoint(nameTexture, pos)
childPos := pos.Add2D(nameTexture.Width()+8, 0) childPos := pos.Add2D(nameTextureWidth+ctx.Style().Dimensions.Margin, 0)
for _, child := range node.Children { for _, child := range node.Children {
if childPos.Y == maxY { if childPos.Y == maxY {
childPos.Y = maxY + nameTexture.Height() childPos.Y = maxY + nameTextureHeight
} }
renderHoverNode(childPos, child) renderHoverNode(childPos, child)
maxY = childPos.Y maxY = childPos.Y
childPos.Y += nameTexture.Height() + 8 childPos.Y += nameTextureHeight + ctx.Style().Dimensions.Margin
} }
} }
renderHoverNode(geom.PtF32(4, 4), o.hoverNodes) renderHoverNode(geom.PtF32(4, 4), o.hoverNodes)

View File

@ -3,6 +3,7 @@ package ui
import ( import (
"image" "image"
"github.com/nfnt/resize"
"opslag.de/schobers/zntg" "opslag.de/schobers/zntg"
) )
@ -45,3 +46,25 @@ func (s ImageSourceResource) CreateImage() (image.Image, error) {
} }
return value.(image.Image), nil return value.(image.Image), nil
} }
func ImageSourceFromResources(res Resources, name string) ImageSourceResource {
return ImageSourceResource{Resources: res, Name: name}
}
func Scaled(source ImageSource, width, height int) ImageSource {
return scaledImageSource{ImageSource: source, width: width, height: height}
}
type scaledImageSource struct {
ImageSource
width, height int
}
func (s scaledImageSource) CreateImage() (image.Image, error) {
im, err := s.ImageSource.CreateImage()
if err != nil {
return nil, err
}
return resize.Resize(uint(s.width), uint(s.height), im, resize.Bicubic), nil
}

View File

@ -1,6 +1,8 @@
package ui package ui
import ( import (
"image/color"
"opslag.de/schobers/geom" "opslag.de/schobers/geom"
) )
@ -8,6 +10,7 @@ type Label struct {
ControlBase ControlBase
Text string Text string
DropShadow color.Color
desired CachedValue desired CachedValue
} }
@ -25,8 +28,7 @@ func (l *Label) hashDesiredSize(ctx Context) string {
} }
func (l *Label) desiredSize(ctx Context) interface{} { func (l *Label) desiredSize(ctx Context) interface{} {
fontName := l.FontName(ctx) font := l.Font_(ctx)
font := ctx.Fonts().Font(fontName)
width := font.WidthOf(l.Text) width := font.WidthOf(l.Text)
height := font.Height() height := font.Height()
pad := ctx.Style().Dimensions.TextPadding pad := ctx.Style().Dimensions.TextPadding
@ -37,18 +39,26 @@ func (l *Label) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 {
return l.desired.GetContext(ctx, l.desiredSize, l.hashDesiredSize).(geom.PointF32) return l.desired.GetContext(ctx, l.desiredSize, l.hashDesiredSize).(geom.PointF32)
} }
func (l *Label) getLabelTopLeft(ctx Context) geom.PointF32 {
pad := ctx.Style().Dimensions.TextPadding
bounds := l.bounds.Inset(pad)
switch l.TextAlignment {
case AlignRight:
return geom.PtF32(bounds.Max.X, bounds.Min.Y)
case AlignCenter:
return geom.PtF32(.5*(bounds.Min.X+bounds.Max.X), bounds.Min.Y)
default:
return bounds.Min
}
}
func (l *Label) Render(ctx Context) { func (l *Label) Render(ctx Context) {
l.RenderBackground(ctx) l.RenderBackground(ctx)
fontColor := l.TextColor(ctx) fontColor := l.TextColor(ctx)
fontName := l.FontName(ctx) fontName := l.FontName(ctx)
pad := ctx.Style().Dimensions.TextPadding topLeft := l.getLabelTopLeft(ctx)
bounds := l.bounds.Inset(pad) if l.DropShadow != nil {
switch l.TextAlignment { ctx.Fonts().TextAlign(fontName, topLeft.Add2D(1, 1), l.DropShadow, l.Text, l.TextAlignment)
case AlignLeft:
ctx.Fonts().TextAlign(fontName, bounds.Min, fontColor, l.Text, l.TextAlignment)
case AlignRight:
ctx.Fonts().TextAlign(fontName, geom.PtF32(bounds.Max.X, bounds.Min.Y), fontColor, l.Text, l.TextAlignment)
case AlignCenter:
ctx.Fonts().TextAlign(fontName, geom.PtF32(.5*(bounds.Min.X+bounds.Max.X), bounds.Min.Y), fontColor, l.Text, l.TextAlignment)
} }
ctx.Fonts().TextAlign(fontName, topLeft, fontColor, l.Text, l.TextAlignment)
} }

View File

@ -23,11 +23,17 @@ type overflow struct {
ver *Scrollbar ver *Scrollbar
} }
func Overflow(content Control) Control { type ScrollControl interface {
Control
SetScrollbarColor(bar color.Color, hover color.Color)
}
func Overflow(content Control) ScrollControl {
return OverflowBackground(content, nil) return OverflowBackground(content, nil)
} }
func OverflowBackground(content Control, back color.Color) Control { func OverflowBackground(content Control, back color.Color) ScrollControl {
var o = &overflow{Proxy: Proxy{Content: content}, Background: back} var o = &overflow{Proxy: Proxy{Content: content}, Background: back}
o.hor = BuildScrollbar(OrientationHorizontal, func(*Scrollbar) {}) o.hor = BuildScrollbar(OrientationHorizontal, func(*Scrollbar) {})
o.ver = BuildScrollbar(OrientationVertical, func(*Scrollbar) {}) o.ver = BuildScrollbar(OrientationVertical, func(*Scrollbar) {})
@ -152,3 +158,10 @@ func (o *overflow) Render(ctx Context) {
bar.Render(ctx) bar.Render(ctx)
}) })
} }
func (o *overflow) SetScrollbarColor(bar color.Color, hover color.Color) {
o.hor.BarColor = bar
o.hor.BarHoverColor = hover
o.ver.BarColor = bar
o.ver.BarHoverColor = hover
}

View File

@ -26,8 +26,7 @@ func BuildParagraph(text string, fn func(*Paragraph)) *Paragraph {
func fastFormatFloat32(f float32) string { return strconv.FormatFloat(float64(f), 'b', 32, 32) } func fastFormatFloat32(f float32) string { return strconv.FormatFloat(float64(f), 'b', 32, 32) }
func (p *Paragraph) desiredSize(ctx Context) interface{} { func (p *Paragraph) desiredSize(ctx Context) interface{} {
fontName := p.FontName(ctx) font := p.Font_(ctx)
font := ctx.Fonts().Font(fontName)
pad := ctx.Style().Dimensions.TextPadding pad := ctx.Style().Dimensions.TextPadding
lines := p.splitInLines(ctx, p.width-2*pad) lines := p.splitInLines(ctx, p.width-2*pad)
@ -43,8 +42,7 @@ func (p *Paragraph) hashTextDesired(ctx Context) string {
} }
func (p *Paragraph) splitInLines(ctx Context, width float32) []string { func (p *Paragraph) splitInLines(ctx Context, width float32) []string {
fontName := p.FontName(ctx) font := p.Font_(ctx)
font := ctx.Fonts().Font(fontName)
spaces := func(s string) []int { // creates a slice with indices where spaces can be found in string s spaces := func(s string) []int { // creates a slice with indices where spaces can be found in string s
var spaces []int var spaces []int

View File

@ -32,8 +32,10 @@ type Renderer interface {
Rectangle(r geom.RectangleF32, c color.Color, thickness float32) Rectangle(r geom.RectangleF32, c color.Color, thickness float32)
RenderTo(Texture) RenderTo(Texture)
RenderToDisplay() RenderToDisplay()
Resize(width, height int)
SetIcon(source ImageSource)
SetMouseCursor(c MouseCursor) SetMouseCursor(c MouseCursor)
Size() geom.PointF32 Size() geom.Point
Target() Texture Target() Texture
Text(font Font, p geom.PointF32, color color.Color, text string) Text(font Font, p geom.PointF32, color color.Color, text string)
TextAlign(font Font, p geom.PointF32, color color.Color, text string, align HorizontalAlignment) TextAlign(font Font, p geom.PointF32, color color.Color, text string, align HorizontalAlignment)

View File

@ -1,6 +1,8 @@
package ui package ui
import ( import (
"image/color"
"opslag.de/schobers/geom" "opslag.de/schobers/geom"
"opslag.de/schobers/zntg" "opslag.de/schobers/zntg"
) )
@ -10,6 +12,8 @@ type Scrollbar struct {
Orientation Orientation Orientation Orientation
BarColor color.Color
BarHoverColor color.Color
ContentLength float32 ContentLength float32
ContentOffset float32 ContentOffset float32
@ -58,7 +62,7 @@ func (s *Scrollbar) Handle(ctx Context, e Event) bool {
func (s *Scrollbar) Render(ctx Context) { func (s *Scrollbar) Render(ctx Context) {
ctx.Renderer().FillRectangle(s.bounds, zntg.RGBA(0, 0, 0, 1)) ctx.Renderer().FillRectangle(s.bounds, zntg.RGBA(0, 0, 0, 1))
s.handle.Render(ctx) s.handle.Render(ctx, s)
} }
func (s *Scrollbar) updateBar(ctx Context) { func (s *Scrollbar) updateBar(ctx Context) {
@ -83,12 +87,22 @@ type ScrollbarHandle struct {
ControlBase ControlBase
} }
func (h *ScrollbarHandle) Render(ctx Context) { func (h *ScrollbarHandle) Render(ctx Context, s *Scrollbar) {
h.RenderBackground(ctx) h.RenderBackground(ctx)
p := ctx.Style().Palette p := ctx.Style().Palette
fill := p.Primary var fill color.Color
if h.over { if h.over {
if s.BarHoverColor == nil {
fill = p.PrimaryLight fill = p.PrimaryLight
} else {
fill = s.BarHoverColor
}
} else {
if s.BarColor == nil {
fill = p.Primary
} else {
fill = s.BarColor
}
} }
ctx.Renderer().FillRectangle(h.bounds.Inset(1), fill) ctx.Renderer().FillRectangle(h.bounds.Inset(1), fill)
} }

View File

@ -12,6 +12,7 @@ var defaultPalette *Palette
var defaultStyle *Style var defaultStyle *Style
type Dimensions struct { type Dimensions struct {
Margin float32
OutlineWidth float32 OutlineWidth float32
ScrollbarWidth float32 ScrollbarWidth float32
TextPadding float32 TextPadding float32
@ -67,6 +68,7 @@ type Style struct {
func DefaultDimensions() *Dimensions { func DefaultDimensions() *Dimensions {
return &Dimensions{ return &Dimensions{
Margin: 8.,
OutlineWidth: 2., OutlineWidth: 2.,
ScrollbarWidth: 16., ScrollbarWidth: 16.,
TextPadding: 8., TextPadding: 8.,

View File

@ -57,8 +57,7 @@ func (b *TextBox) Arrange(ctx Context, bounds geom.RectangleF32, offset geom.Poi
} }
func (b *TextBox) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 { func (b *TextBox) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 {
var fontName = b.FontName(ctx) font := b.Font_(ctx)
var font = ctx.Fonts().Font(fontName)
var width = font.WidthOf(b.Text) var width = font.WidthOf(b.Text)
var height = font.Height() var height = font.Height()
var pad = b.pad(ctx) var pad = b.pad(ctx)
@ -68,7 +67,7 @@ func (b *TextBox) DesiredSize(ctx Context, _ geom.PointF32) geom.PointF32 {
func (b *TextBox) mousePosToCaretPos(ctx Context, e MouseEvent) int { func (b *TextBox) mousePosToCaretPos(ctx Context, e MouseEvent) int {
p := b.ToControlPosition(e.Pos()) p := b.ToControlPosition(e.Pos())
offset := p.X - b.box.bounds.Min.X offset := p.X - b.box.bounds.Min.X
f := ctx.Fonts().Font(b.FontName(ctx)) f := b.Font_(ctx)
var carets = [3]int{0, 0, len(b.Text)} var carets = [3]int{0, 0, len(b.Text)}
var offsets = [3]float32{0, 0, f.WidthOf(b.Text)} var offsets = [3]float32{0, 0, f.WidthOf(b.Text)}
var updateCenter = func() { var updateCenter = func() {
@ -259,8 +258,7 @@ func (b *TextBox) Render(ctx Context) {
back = ctx.Style().Palette.Background back = ctx.Style().Palette.Background
} }
renderer.Clear(back) renderer.Clear(back)
fontName := b.FontName(ctx) font := b.Font_(ctx)
font := ctx.Fonts().Font(fontName)
if b.Selection.Start != b.Selection.End { if b.Selection.Start != b.Selection.End {
left, right := font.WidthOf(b.Text[:b.Selection.Start]), font.WidthOf(b.Text[:b.Selection.End]) left, right := font.WidthOf(b.Text[:b.Selection.Start]), font.WidthOf(b.Text[:b.Selection.End])
renderer.FillRectangle(geom.RectF32(left, 0, right, size.Y), style.Palette.PrimaryHighlight) renderer.FillRectangle(geom.RectF32(left, 0, right, size.Y), style.Palette.PrimaryHighlight)

View File

@ -4,8 +4,8 @@ import "opslag.de/schobers/geom"
type Texture interface { type Texture interface {
Destroy() error Destroy() error
Height() float32 Height() int
Width() float32 Width() int
} }
func SizeOfTexture(t Texture) geom.PointF32 { return geom.PtF32(t.Width(), t.Height()) } func SizeOfTexture(t Texture) geom.Point { return geom.Pt(t.Width(), t.Height()) }

View File

@ -8,7 +8,7 @@ import (
) )
func ScaleTexture(render Renderer, texture Texture, scale float32) Texture { func ScaleTexture(render Renderer, texture Texture, scale float32) Texture {
w := uint(texture.Width() * scale) w := uint(float32(texture.Width()) * scale)
if w == 0 { if w == 0 {
return nil return nil
} }
@ -118,7 +118,7 @@ func (t *Textures) Scaled(texture Texture, scale float32) Texture {
} }
func (t *Textures) ScaledHeight(texture Texture, height float32) (Texture, float32) { func (t *Textures) ScaledHeight(texture Texture, height float32) (Texture, float32) {
scale := height / texture.Height() scale := height / float32(texture.Height())
if geom.IsNaN32(scale) { if geom.IsNaN32(scale) {
return nil, 0 return nil, 0
} }

View File

@ -46,7 +46,7 @@ func RunWait(r Renderer, s *Style, view Control, wait bool) error {
ctx.Renderer().Refresh() ctx.Renderer().Refresh()
for !ctx.HasQuit() { for !ctx.HasQuit() {
var size = r.Size() var size = r.Size()
var bounds = geom.RectF32(0, 0, size.X, size.Y) var bounds = geom.RectF32(0, 0, float32(size.X), float32(size.Y))
overlays.Arrange(ctx, bounds, geom.ZeroPtF32, nil) overlays.Arrange(ctx, bounds, geom.ZeroPtF32, nil)
overlays.Render(ctx) overlays.Render(ctx)
if ctx.HasQuit() { if ctx.HasQuit() {