Compare commits
8 Commits
f3ce48a1ba
...
102c187566
Author | SHA1 | Date | |
---|---|---|---|
102c187566 | |||
11e37af9c2 | |||
5babda0ca9 | |||
b1cdbea90f | |||
7d5168614e | |||
b0a13d1a3c | |||
cc32cf5bc3 | |||
0f03760e66 |
@ -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) {
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
@ -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{}
|
||||||
|
27
ui/button.go
27
ui/button.go
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
10
ui/debug.go
10
ui/debug.go
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
32
ui/label.go
32
ui/label.go
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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.,
|
||||||
|
@ -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)
|
||||||
|
@ -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()) }
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
2
ui/ui.go
2
ui/ui.go
@ -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() {
|
||||||
|
Loading…
Reference in New Issue
Block a user