283 lines
4.7 KiB
Go
283 lines
4.7 KiB
Go
|
// Copyright 2017 The Walk Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
// +build windows
|
||
|
|
||
|
package walk
|
||
|
|
||
|
import (
|
||
|
"unsafe"
|
||
|
|
||
|
"github.com/lxn/win"
|
||
|
)
|
||
|
|
||
|
type GradientComposite struct {
|
||
|
*Composite
|
||
|
vertical bool
|
||
|
color1 Color
|
||
|
color2 Color
|
||
|
verticalChangedPublisher EventPublisher
|
||
|
color1ChangedPublisher EventPublisher
|
||
|
color2ChangedPublisher EventPublisher
|
||
|
brush *BitmapBrush
|
||
|
}
|
||
|
|
||
|
func NewGradientComposite(parent Container) (*GradientComposite, error) {
|
||
|
return NewGradientCompositeWithStyle(parent, 0)
|
||
|
}
|
||
|
|
||
|
func NewGradientCompositeWithStyle(parent Container, style uint32) (*GradientComposite, error) {
|
||
|
composite, err := NewCompositeWithStyle(parent, style)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
gc := &GradientComposite{Composite: composite}
|
||
|
|
||
|
succeeded := false
|
||
|
defer func() {
|
||
|
if !succeeded {
|
||
|
gc.Dispose()
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
if err := InitWrapperWindow(gc); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
gc.MustRegisterProperty("Vertical", NewBoolProperty(
|
||
|
func() bool {
|
||
|
return gc.Vertical()
|
||
|
},
|
||
|
func(b bool) error {
|
||
|
gc.SetVertical(b)
|
||
|
return nil
|
||
|
},
|
||
|
gc.verticalChangedPublisher.Event()))
|
||
|
|
||
|
gc.MustRegisterProperty("Color1", NewProperty(
|
||
|
func() interface{} {
|
||
|
return float64(uint32(gc.Color1()))
|
||
|
},
|
||
|
func(v interface{}) error {
|
||
|
var c Color
|
||
|
|
||
|
switch v := v.(type) {
|
||
|
case Color:
|
||
|
c = v
|
||
|
|
||
|
case uint32:
|
||
|
c = Color(v)
|
||
|
|
||
|
case float64:
|
||
|
c = Color(uint32(v))
|
||
|
|
||
|
default:
|
||
|
return ErrInvalidType
|
||
|
}
|
||
|
|
||
|
return gc.SetColor1(c)
|
||
|
},
|
||
|
gc.color1ChangedPublisher.Event()))
|
||
|
|
||
|
gc.MustRegisterProperty("Color2", NewProperty(
|
||
|
func() interface{} {
|
||
|
return float64(uint32(gc.Color2()))
|
||
|
},
|
||
|
func(v interface{}) error {
|
||
|
var c Color
|
||
|
|
||
|
switch v := v.(type) {
|
||
|
case Color:
|
||
|
c = v
|
||
|
|
||
|
case uint32:
|
||
|
c = Color(v)
|
||
|
|
||
|
case float64:
|
||
|
c = Color(uint32(v))
|
||
|
|
||
|
default:
|
||
|
return ErrInvalidType
|
||
|
}
|
||
|
|
||
|
return gc.SetColor2(c)
|
||
|
},
|
||
|
gc.color2ChangedPublisher.Event()))
|
||
|
|
||
|
succeeded = true
|
||
|
|
||
|
return gc, nil
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) Vertical() bool {
|
||
|
return gc.vertical
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) SetVertical(vertical bool) (err error) {
|
||
|
if vertical == gc.vertical {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
old := gc.vertical
|
||
|
|
||
|
defer func() {
|
||
|
if err != nil {
|
||
|
gc.vertical = old
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
gc.vertical = vertical
|
||
|
|
||
|
if err = gc.updateBackground(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
gc.verticalChangedPublisher.Publish()
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) Color1() Color {
|
||
|
return gc.color1
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) SetColor1(c Color) (err error) {
|
||
|
if c == gc.color1 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
old := gc.color1
|
||
|
|
||
|
defer func() {
|
||
|
if err != nil {
|
||
|
gc.color1 = old
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
gc.color1 = c
|
||
|
|
||
|
if err = gc.updateBackground(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
gc.color1ChangedPublisher.Publish()
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) Color2() Color {
|
||
|
return gc.color2
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) SetColor2(c Color) (err error) {
|
||
|
if c == gc.color2 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
old := gc.color2
|
||
|
|
||
|
defer func() {
|
||
|
if err != nil {
|
||
|
gc.color2 = old
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
gc.color2 = c
|
||
|
|
||
|
if err = gc.updateBackground(); err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
gc.color2ChangedPublisher.Publish()
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) updateBackground() error {
|
||
|
bounds := gc.ClientBoundsPixels()
|
||
|
if bounds.Width < 1 || bounds.Height < 1 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if gc.brush != nil {
|
||
|
gc.brush.Dispose()
|
||
|
gc.brush.Bitmap().Dispose()
|
||
|
gc.brush = nil
|
||
|
}
|
||
|
|
||
|
if gc.vertical {
|
||
|
bounds.Width = 1
|
||
|
} else {
|
||
|
bounds.Height = 1
|
||
|
}
|
||
|
|
||
|
bmp, err := NewBitmapForDPI(bounds.Size(), gc.DPI())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer func() {
|
||
|
if gc.brush == nil {
|
||
|
bmp.Dispose()
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
canvas, err := NewCanvasFromImage(bmp)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer canvas.Dispose()
|
||
|
|
||
|
var orientation Orientation
|
||
|
if gc.vertical {
|
||
|
orientation = Vertical
|
||
|
} else {
|
||
|
orientation = Horizontal
|
||
|
}
|
||
|
|
||
|
if err := canvas.GradientFillRectanglePixels(gc.color1, gc.color2, orientation, bounds); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
gc.brush, err = NewBitmapBrush(bmp)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
gc.SetBackground(gc.brush)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) Dispose() {
|
||
|
if gc.brush != nil {
|
||
|
gc.SetBackground(nil)
|
||
|
gc.brush.Dispose()
|
||
|
gc.brush.Bitmap().Dispose()
|
||
|
gc.brush = nil
|
||
|
}
|
||
|
|
||
|
gc.Composite.Dispose()
|
||
|
}
|
||
|
|
||
|
func (gc *GradientComposite) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
|
||
|
switch msg {
|
||
|
case win.WM_WINDOWPOSCHANGED:
|
||
|
wp := (*win.WINDOWPOS)(unsafe.Pointer(lParam))
|
||
|
|
||
|
if wp.Flags&win.SWP_NOSIZE != 0 {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
size := gc.ClientBoundsPixels().Size()
|
||
|
if gc.brush != nil && gc.brush.bitmap.size == size {
|
||
|
break
|
||
|
}
|
||
|
|
||
|
gc.updateBackground()
|
||
|
}
|
||
|
|
||
|
return gc.Composite.WndProc(hwnd, msg, wParam, lParam)
|
||
|
}
|