Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add scroll bar to ScrollContainer
Just vertical, as we have no horiz scroll yet.
Fixes #31
  • Loading branch information
andydotxyz committed Feb 24, 2019
1 parent 65af4c5 commit 484b862
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 5 deletions.
8 changes: 8 additions & 0 deletions cmd/fyne_demo/theme.go
Expand Up @@ -44,6 +44,10 @@ func (customTheme) FocusColor() color.Color {
return orange
}

func (customTheme) ScrollBarColor() color.Color {
return grey
}

func (customTheme) TextSize() int {
return 12
}
Expand Down Expand Up @@ -76,6 +80,10 @@ func (customTheme) IconInlineSize() int {
return 20
}

func (customTheme) ScrollBarSize() int {
return 10
}

func newCustomTheme() fyne.Theme {
return &customTheme{}
}
2 changes: 1 addition & 1 deletion driver/gl/draw.go
Expand Up @@ -216,7 +216,7 @@ func (c *glCanvas) drawRectangle(rect *canvas.Rectangle, pos fyne.Position, fram
points := c.rectCoords(rect.Size(), pos, frame, canvas.ImageFillStretch, 0.0, 0)
texture := getTexture(rect, c.newGlRectTexture)

gl.Disable(gl.BLEND)
gl.Enable(gl.BLEND) // enable translucency
c.drawTexture(texture, points)
}

Expand Down
8 changes: 8 additions & 0 deletions test/testapp.go
Expand Up @@ -131,10 +131,18 @@ func (dummyTheme) FocusColor() color.Color {
return color.Black
}

func (dummyTheme) ScrollBarColor() color.Color {
return color.Black
}

func (dummyTheme) TextSize() int {
return 10
}

func (dummyTheme) ScrollBarSize() int {
return 10
}

func (dummyTheme) TextFont() fyne.Resource {
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions theme.go
Expand Up @@ -11,6 +11,7 @@ type Theme interface {
PlaceHolderColor() color.Color
PrimaryColor() color.Color
FocusColor() color.Color
ScrollBarColor() color.Color

TextSize() int
TextFont() Resource
Expand All @@ -21,4 +22,5 @@ type Theme interface {

Padding() int
IconInlineSize() int
ScrollBarSize() int
}
26 changes: 24 additions & 2 deletions theme/theme.go
Expand Up @@ -15,8 +15,8 @@ import (
type builtinTheme struct {
background color.Color

button, text, hyperlink, placeholder, primary color.Color
regular, bold, italic, bolditalic, monospace fyne.Resource
button, text, hyperlink, placeholder, primary, scrollBar color.Color
regular, bold, italic, bolditalic, monospace fyne.Resource
}

var lightBackground = color.RGBA{0xf5, 0xf5, 0xf5, 0xff}
Expand All @@ -30,6 +30,7 @@ func LightTheme() fyne.Theme {
hyperlink: color.RGBA{0x0, 0x0, 0xd9, 0xff},
placeholder: color.RGBA{0x88, 0x88, 0x88, 0xff},
primary: color.RGBA{0x9f, 0xa8, 0xda, 0xff},
scrollBar: color.RGBA{0x0, 0x0, 0x0, 0x99},
}

theme.initFonts()
Expand All @@ -45,6 +46,7 @@ func DarkTheme() fyne.Theme {
hyperlink: color.RGBA{0x99, 0x99, 0xff, 0xff},
placeholder: color.RGBA{0xb2, 0xb2, 0xb2, 0xff},
primary: color.RGBA{0x1a, 0x23, 0x7e, 0xff},
scrollBar: color.RGBA{0x0, 0x0, 0x0, 0x99},
}

theme.initFonts()
Expand Down Expand Up @@ -85,6 +87,11 @@ func (t *builtinTheme) FocusColor() color.Color {
return t.primary
}

// ScrollBarColor returns the color (and translucency) for a scrollBar
func (t *builtinTheme) ScrollBarColor() color.Color {
return t.scrollBar
}

// TextSize returns the standard text size
func (t *builtinTheme) TextSize() int {
return 14
Expand Down Expand Up @@ -165,6 +172,11 @@ func (t *builtinTheme) IconInlineSize() int {
return 20
}

// ScrollBarSize is the width (or height) of the bars on a ScrollContainer
func (t *builtinTheme) ScrollBarSize() int {
return 16
}

func current() fyne.Theme {
// if fyne.CurrentApp().Theme() != nil
return fyne.CurrentApp().Settings().Theme()
Expand Down Expand Up @@ -205,6 +217,11 @@ func FocusColor() color.Color {
return current().FocusColor()
}

// ScrollBarColor returns the color (and translucency) for a scrollBar
func ScrollBarColor() color.Color {
return current().ScrollBarColor()
}

// TextSize returns the standard text size
func TextSize() int {
return current().TextSize()
Expand Down Expand Up @@ -246,6 +263,11 @@ func IconInlineSize() int {
return current().IconInlineSize()
}

// ScrollBarSize is the width (or height) of the bars on a ScrollContainer
func ScrollBarSize() int {
return current().ScrollBarSize()
}

// DefaultTextFont returns the font path for the built-in regular font style
func DefaultTextFont() fyne.Resource {
return regular
Expand Down
31 changes: 29 additions & 2 deletions widget/scroller.go
Expand Up @@ -9,7 +9,8 @@ import (
)

type scrollRenderer struct {
scroll *ScrollContainer
scroll *ScrollContainer
vertBar *canvas.Rectangle

objects []fyne.CanvasObject
}
Expand All @@ -24,12 +25,36 @@ func (s *scrollRenderer) updatePosition() {
}
s.scroll.Content.Move(fyne.NewPos(-s.scroll.Offset.X, -s.scroll.Offset.Y))
canvas.Refresh(s.scroll.Content)

s.updateBarPosition()
}

func (s *scrollRenderer) updateBarPosition() {
barSize := s.barSizeVertical()
barRatio := float32(s.scroll.Offset.Y) / float32(s.scroll.Content.Size().Height-s.scroll.Size().Height)
barOff := int(float32(s.scroll.size.Height-barSize.Height) * barRatio)

s.vertBar.Resize(barSize)
s.vertBar.Move(fyne.NewPos(s.scroll.size.Width-theme.ScrollBarSize(), barOff))
}

func (s *scrollRenderer) barSizeVertical() fyne.Size {
portion := float32(s.scroll.size.Height) / float32(s.scroll.Content.Size().Height)
if portion > 1.0 {
portion = 1.0
}

barHeight := int(float32(s.scroll.size.Height) * portion)
return fyne.NewSize(theme.ScrollBarSize(), barHeight)
}

func (s *scrollRenderer) Layout(size fyne.Size) {
c := s.scroll.Content
c.Resize(c.MinSize())

s.vertBar.Resize(fyne.NewSize(theme.ScrollBarSize(), size.Height))
s.vertBar.Move(fyne.NewPos(size.Width-theme.ScrollBarSize(), 0))

s.updatePosition()
}

Expand All @@ -43,6 +68,7 @@ func (s *scrollRenderer) Refresh() {
}

func (s *scrollRenderer) ApplyTheme() {
s.vertBar.FillColor = theme.ScrollBarColor()
}

func (s *scrollRenderer) BackgroundColor() color.Color {
Expand Down Expand Up @@ -108,7 +134,8 @@ func (s *ScrollContainer) Hide() {

// CreateRenderer is a private method to Fyne which links this widget to it's renderer
func (s *ScrollContainer) CreateRenderer() fyne.WidgetRenderer {
return &scrollRenderer{scroll: s, objects: []fyne.CanvasObject{s.Content}}
bar := canvas.NewRectangle(theme.ScrollBarColor())
return &scrollRenderer{scroll: s, vertBar: bar, objects: []fyne.CanvasObject{s.Content, bar}}
}

// NewScroller creates a scrollable parent wrapping the specified content.
Expand Down
15 changes: 15 additions & 0 deletions widget/scroller_test.go
Expand Up @@ -6,6 +6,7 @@ import (

"fyne.io/fyne"
"fyne.io/fyne/canvas"
"fyne.io/fyne/theme"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -62,3 +63,17 @@ func TestScrollContainer_Resize(t *testing.T) {
scroll.Resize(fyne.NewSize(80, 100))
assert.Equal(t, 0, scroll.Offset.Y)
}

func TestScrollContainerRenderer_BarSize(t *testing.T) {
rect := canvas.NewRectangle(color.Black)
rect.SetMinSize(fyne.NewSize(100, 100))
scroll := NewScroller(rect)
scroll.Resize(fyne.NewSize(100, 100))
render := Renderer(scroll).(*scrollRenderer)

assert.Equal(t, fyne.NewSize(theme.ScrollBarSize(), 100), render.barSizeVertical())

// resize so content is twice our size. Bar should therefore be half again.
scroll.Resize(fyne.NewSize(50, 50))
assert.Equal(t, fyne.NewSize(theme.ScrollBarSize(), 25), render.barSizeVertical())
}

0 comments on commit 484b862

Please sign in to comment.