Add support for transparency
Need to break away from ggfx to do this, probably put everything in xcanvas.
This commit is contained in:
parent
45fa282b61
commit
8401b5d0f9
150
box.go
150
box.go
@ -23,6 +23,9 @@ type box struct {
|
||||
padding tomo.Inset
|
||||
border []tomo.Border
|
||||
color color.Color
|
||||
texture *texture
|
||||
|
||||
fillTransparent bool
|
||||
|
||||
dndData data.Data
|
||||
dndAccept []data.Mime
|
||||
@ -111,13 +114,22 @@ func (this *box) SetBounds (bounds image.Rectangle) {
|
||||
}
|
||||
|
||||
func (this *box) SetColor (c color.Color) {
|
||||
if c == nil { c = color.Transparent }
|
||||
if this.color == c { return }
|
||||
this.color = c
|
||||
this.determineFillTransparency()
|
||||
this.invalidateDraw()
|
||||
}
|
||||
|
||||
func (this *box) SetTexture (texture tomo.Texture) {
|
||||
this.texture = assertTexture(texture)
|
||||
this.determineFillTransparency()
|
||||
this.invalidateDraw()
|
||||
}
|
||||
|
||||
func (this *box) SetBorder (border ...tomo.Border) {
|
||||
this.border = border
|
||||
this.determineFillTransparency()
|
||||
this.invalidateLayout()
|
||||
this.invalidateMinimum()
|
||||
}
|
||||
@ -221,44 +233,103 @@ func (this *box) OnKeyDown (callback func(key input.Key, numberPad bool)) event.
|
||||
func (this *box) OnKeyUp (callback func(key input.Key, numberPad bool)) event.Cookie {
|
||||
return this.on.keyUp.Connect(callback)
|
||||
}
|
||||
func (this *box) handleFocusEnter () {
|
||||
this.on.focusEnter.Broadcast()
|
||||
}
|
||||
func (this *box) handleFocusLeave () {
|
||||
this.on.focusLeave.Broadcast()
|
||||
}
|
||||
func (this *box) handleMouseEnter () {
|
||||
this.on.mouseEnter.Broadcast()
|
||||
}
|
||||
func (this *box) handleMouseLeave () {
|
||||
this.on.mouseLeave.Broadcast()
|
||||
}
|
||||
func (this *box) handleMouseMove () {
|
||||
this.on.mouseMove.Broadcast()
|
||||
}
|
||||
func (this *box) handleMouseDown (button input.Button) {
|
||||
if this.focusable {
|
||||
this.SetFocused(true)
|
||||
} else {
|
||||
if this.parent == nil { return }
|
||||
window := this.parent.window()
|
||||
if window == nil { return }
|
||||
window.focus(nil)
|
||||
}
|
||||
for _, listener := range this.on.mouseDown.Listeners() {
|
||||
listener(button)
|
||||
}
|
||||
}
|
||||
func (this *box) handleMouseUp (button input.Button) {
|
||||
for _, listener := range this.on.mouseUp.Listeners() {
|
||||
listener(button)
|
||||
}
|
||||
}
|
||||
func (this *box) handleKeyDown (key input.Key, numberPad bool) {
|
||||
for _, listener := range this.on.keyDown.Listeners() {
|
||||
listener(key, numberPad)
|
||||
}
|
||||
}
|
||||
func (this *box) handleKeyUp (key input.Key, numberPad bool) {
|
||||
for _, listener := range this.on.keyUp.Listeners() {
|
||||
listener(key, numberPad)
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func (this *box) Draw (can canvas.Canvas) {
|
||||
if can == nil { return }
|
||||
pen := can.Pen()
|
||||
pen.Fill(this.color)
|
||||
if this.texture == nil || this.texture.transparent {
|
||||
pen.Rectangle(this.bounds)
|
||||
}
|
||||
if this.texture != nil {
|
||||
// TODO drawR texture
|
||||
}
|
||||
}
|
||||
|
||||
func (this *box) drawBorders (can canvas.Canvas) {
|
||||
if can == nil { return }
|
||||
pen := can.Pen()
|
||||
bounds := this.bounds
|
||||
|
||||
rectangle := func (x0, y0, x1, y1 int, c color.Color) {
|
||||
area := image.Rect(x0, y0, x1, y1)
|
||||
_, _, _, a := c.RGBA()
|
||||
if a != 0xFFFF && this.parent != nil {
|
||||
this.parent.drawBackgroundPart(can.Clip(area))
|
||||
}
|
||||
pen.Fill(c)
|
||||
pen.Rectangle(area)
|
||||
}
|
||||
|
||||
for _, border := range this.border {
|
||||
pen.Fill(border.Color[tomo.SideTop])
|
||||
pen.Rectangle(image.Rect (
|
||||
rectangle (
|
||||
bounds.Min.X,
|
||||
bounds.Min.Y,
|
||||
bounds.Max.X,
|
||||
bounds.Min.Y + border.Width[tomo.SideTop]))
|
||||
pen.Fill(border.Color[tomo.SideBottom])
|
||||
pen.Rectangle(image.Rect (
|
||||
bounds.Min.Y + border.Width[tomo.SideTop],
|
||||
border.Color[tomo.SideTop])
|
||||
rectangle (
|
||||
bounds.Min.X,
|
||||
bounds.Max.Y - border.Width[tomo.SideBottom],
|
||||
bounds.Max.X,
|
||||
bounds.Max.Y))
|
||||
pen.Fill(border.Color[tomo.SideLeft])
|
||||
pen.Rectangle(image.Rect (
|
||||
bounds.Max.Y,
|
||||
border.Color[tomo.SideBottom])
|
||||
rectangle (
|
||||
bounds.Min.X,
|
||||
bounds.Min.Y + border.Width[tomo.SideTop],
|
||||
bounds.Min.X + border.Width[tomo.SideLeft],
|
||||
bounds.Max.Y - border.Width[tomo.SideBottom]))
|
||||
pen.Fill(border.Color[tomo.SideRight])
|
||||
pen.Rectangle(image.Rect (
|
||||
bounds.Max.Y - border.Width[tomo.SideBottom],
|
||||
border.Color[tomo.SideLeft])
|
||||
rectangle (
|
||||
bounds.Max.X - border.Width[tomo.SideRight],
|
||||
bounds.Min.Y + border.Width[tomo.SideTop],
|
||||
bounds.Max.X,
|
||||
bounds.Max.Y - border.Width[tomo.SideBottom]))
|
||||
bounds.Max.Y - border.Width[tomo.SideBottom],
|
||||
border.Color[tomo.SideRight])
|
||||
|
||||
bounds = border.Width.Apply(bounds)
|
||||
}
|
||||
@ -356,56 +427,11 @@ func (this *box) boxUnder (point image.Point) anyBox {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *box) handleFocusEnter () {
|
||||
this.on.focusEnter.Broadcast()
|
||||
}
|
||||
|
||||
func (this *box) handleFocusLeave () {
|
||||
this.on.focusLeave.Broadcast()
|
||||
}
|
||||
|
||||
func (this *box) handleMouseEnter () {
|
||||
this.on.mouseEnter.Broadcast()
|
||||
}
|
||||
|
||||
func (this *box) handleMouseLeave () {
|
||||
this.on.mouseLeave.Broadcast()
|
||||
}
|
||||
|
||||
func (this *box) handleMouseMove () {
|
||||
this.on.mouseMove.Broadcast()
|
||||
}
|
||||
|
||||
func (this *box) handleMouseDown (button input.Button) {
|
||||
if this.focusable {
|
||||
this.SetFocused(true)
|
||||
} else {
|
||||
if this.parent == nil { return }
|
||||
window := this.parent.window()
|
||||
if window == nil { return }
|
||||
window.focus(nil)
|
||||
}
|
||||
for _, listener := range this.on.mouseDown.Listeners() {
|
||||
listener(button)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *box) handleMouseUp (button input.Button) {
|
||||
for _, listener := range this.on.mouseUp.Listeners() {
|
||||
listener(button)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *box) handleKeyDown (key input.Key, numberPad bool) {
|
||||
for _, listener := range this.on.keyDown.Listeners() {
|
||||
listener(key, numberPad)
|
||||
}
|
||||
}
|
||||
|
||||
func (this *box) handleKeyUp (key input.Key, numberPad bool) {
|
||||
for _, listener := range this.on.keyUp.Listeners() {
|
||||
listener(key, numberPad)
|
||||
}
|
||||
func (this *box) determineFillTransparency () {
|
||||
_, _, _, a := this.color.RGBA()
|
||||
this.fillTransparent =
|
||||
a != 0xFFFF &&
|
||||
!(this.texture != nil && !this.texture.transparent)
|
||||
}
|
||||
|
||||
func (this *box) propagate (callback func (anyBox) bool) bool {
|
||||
|
@ -132,7 +132,6 @@ func (this *containerBox) SetLayout (layout tomo.Layout) {
|
||||
|
||||
func (this *containerBox) Draw (can canvas.Canvas) {
|
||||
if can == nil { return }
|
||||
this.drawBorders(can)
|
||||
pen := can.Pen()
|
||||
pen.Fill(this.color)
|
||||
|
||||
@ -141,8 +140,34 @@ func (this *containerBox) Draw (can canvas.Canvas) {
|
||||
rocks[index] = box.Bounds()
|
||||
}
|
||||
for _, tile := range canvas.Shatter(this.bounds, rocks...) {
|
||||
if this.fillTransparent && this.parent != nil {
|
||||
this.parent.drawBackgroundPart(can.Clip(tile))
|
||||
}
|
||||
if this.texture == nil || this.texture.transparent {
|
||||
pen.Rectangle(tile)
|
||||
}
|
||||
if this.texture != nil {
|
||||
// TODO draw texture
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (this *containerBox) drawBackgroundPart (can canvas.Canvas) {
|
||||
if can == nil { return }
|
||||
|
||||
if this.fillTransparent && this.parent != nil {
|
||||
this.parent.drawBackgroundPart(can)
|
||||
}
|
||||
|
||||
pen := can.Pen()
|
||||
pen.Fill(this.color)
|
||||
|
||||
if this.texture == nil || this.texture.transparent {
|
||||
pen.Rectangle(can.Bounds())
|
||||
}
|
||||
if this.texture != nil {
|
||||
// TODO draw texture
|
||||
}
|
||||
}
|
||||
|
||||
func (this *containerBox) flushActionQueue () {
|
||||
|
2
go.mod
2
go.mod
@ -4,7 +4,7 @@ go 1.20
|
||||
|
||||
require (
|
||||
git.tebibyte.media/tomo/ggfx v0.4.0
|
||||
git.tebibyte.media/tomo/tomo v0.24.0
|
||||
git.tebibyte.media/tomo/tomo v0.25.0
|
||||
git.tebibyte.media/tomo/typeset v0.5.2
|
||||
git.tebibyte.media/tomo/xgbkb v1.0.1
|
||||
github.com/jezek/xgb v1.1.0
|
||||
|
4
go.sum
4
go.sum
@ -1,8 +1,8 @@
|
||||
git.tebibyte.media/sashakoshka/xgbkb v1.0.0/go.mod h1:pNcE6TRO93vHd6q42SdwLSTTj25L0Yzggz7yLe0JV6Q=
|
||||
git.tebibyte.media/tomo/ggfx v0.4.0 h1:3aUHeGS/yYWRV/zCDubBsXnik5ygkMnj/VgrM5Z75A4=
|
||||
git.tebibyte.media/tomo/ggfx v0.4.0/go.mod h1:zPoz8BdVQyG2KhEmeGFQBK66V71i6Kj8oVFbrZaCwRA=
|
||||
git.tebibyte.media/tomo/tomo v0.24.0 h1:Zv5S/SmGjoEzssIOx/ADZBmnIfdeeVEwHdHVQHcls9M=
|
||||
git.tebibyte.media/tomo/tomo v0.24.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps=
|
||||
git.tebibyte.media/tomo/tomo v0.25.0 h1:nFZATsIqLQyGNB1QreVTFhFQjbyBax1hjMff2u1qpxc=
|
||||
git.tebibyte.media/tomo/tomo v0.25.0/go.mod h1:C9EzepS9wjkTJjnZaPBh22YvVPyA4hbBAJVU20Rdmps=
|
||||
git.tebibyte.media/tomo/typeset v0.5.2 h1:qHxN62/VDnrAouOuzxLmLleQNwAebshrfVYvtoOnAG4=
|
||||
git.tebibyte.media/tomo/typeset v0.5.2/go.mod h1:PwDpSdBF3l/EzoIsa2ME7QffVVajnTHZN6l3MHEGe1g=
|
||||
git.tebibyte.media/tomo/xgbkb v1.0.1 h1:b3HDUopjdQp1MZrb5Vpil4bOtk3NnNXtfQW27Blw2kE=
|
||||
|
@ -36,6 +36,7 @@ type parent interface {
|
||||
window () *window
|
||||
canvas () canvas.Canvas
|
||||
notifyMinimumSizeChange (anyBox)
|
||||
drawBackgroundPart (canvas.Canvas)
|
||||
}
|
||||
|
||||
type anyBox interface {
|
||||
|
@ -46,3 +46,11 @@ func (this *texture) Clip (bounds image.Rectangle) tomo.Texture {
|
||||
func (this *texture) Close () error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertTexture (unknown tomo.Texture) *texture {
|
||||
if tx, ok := unknown.(*texture); ok {
|
||||
return tx
|
||||
} else {
|
||||
panic("foregin texture implementation, i did not make this!")
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import "git.tebibyte.media/tomo/x/canvas"
|
||||
import "git.tebibyte.media/tomo/tomo/data"
|
||||
import "git.tebibyte.media/tomo/tomo/input"
|
||||
import "git.tebibyte.media/tomo/tomo/event"
|
||||
import "git.tebibyte.media/tomo/tomo/canvas"
|
||||
|
||||
import "github.com/jezek/xgb/xproto"
|
||||
import "github.com/jezek/xgbutil/ewmh"
|
||||
@ -361,6 +362,11 @@ func (window *window) pushRegion (region image.Rectangle) {
|
||||
subCanvas.(*xcanvas.Canvas).Push(window.xWindow.Id)
|
||||
}
|
||||
|
||||
func (window *window) drawBackgroundPart (canvas.Canvas) {
|
||||
// no-op for now? maybe eventually windows will be able to have a
|
||||
// background
|
||||
}
|
||||
|
||||
func (window *window) doMinimumSize () {
|
||||
window.minimumClean = true
|
||||
|
||||
|
Reference in New Issue
Block a user