mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 18:29:53 +08:00

* fix: fix go test errors * Add flags to mac test * Run on all branches * Update PR workflow Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
343 lines
7.3 KiB
Go
343 lines
7.3 KiB
Go
//go:build windows
|
|
|
|
/*
|
|
* Copyright (C) 2019 The Winc Authors. All Rights Reserved.
|
|
*/
|
|
|
|
package winc
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
|
|
)
|
|
|
|
type direction int
|
|
|
|
const (
|
|
DirNone direction = iota
|
|
DirX
|
|
DirY
|
|
DirX2
|
|
DirY2
|
|
)
|
|
|
|
var ImageBoxPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(140, 140, 220)))
|
|
var ImageBoxHiPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(220, 140, 140)))
|
|
var ImageBoxMarkBrush = NewSolidColorBrush(RGB(40, 40, 40))
|
|
var ImageBoxMarkPen = NewPen(w32.PS_GEOMETRIC, 2, ImageBoxMarkBrush)
|
|
|
|
type ImageBox struct {
|
|
Name string
|
|
Type int
|
|
X, Y, X2, Y2 int
|
|
|
|
underMouse bool // dynamic value
|
|
}
|
|
|
|
func (b *ImageBox) Rect() *Rect {
|
|
return NewRect(b.X, b.Y, b.X2, b.Y2)
|
|
}
|
|
|
|
// ImageViewBox is image view with boxes.
|
|
type ImageViewBox struct {
|
|
ControlBase
|
|
|
|
bmp *Bitmap
|
|
mouseLeft bool
|
|
modified bool // used by GUI to see if any image box modified
|
|
|
|
add bool
|
|
|
|
Boxes []*ImageBox // might be persisted to file
|
|
dragBox *ImageBox
|
|
selBox *ImageBox
|
|
|
|
dragStartX, dragStartY int
|
|
resize direction
|
|
|
|
onSelectedChange EventManager
|
|
onAdd EventManager
|
|
onModify EventManager
|
|
}
|
|
|
|
func NewImageViewBox(parent Controller) *ImageViewBox {
|
|
iv := new(ImageViewBox)
|
|
|
|
iv.InitWindow("winc_ImageViewBox", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE)
|
|
RegMsgHandler(iv)
|
|
|
|
iv.SetFont(DefaultFont)
|
|
iv.SetText("")
|
|
iv.SetSize(200, 65)
|
|
|
|
return iv
|
|
}
|
|
|
|
func (iv *ImageViewBox) OnSelectedChange() *EventManager {
|
|
return &iv.onSelectedChange
|
|
}
|
|
|
|
func (iv *ImageViewBox) OnAdd() *EventManager {
|
|
return &iv.onAdd
|
|
}
|
|
|
|
func (iv *ImageViewBox) OnModify() *EventManager {
|
|
return &iv.onModify
|
|
}
|
|
|
|
func (iv *ImageViewBox) IsModified() bool { return iv.modified }
|
|
func (iv *ImageViewBox) SetModified(modified bool) { iv.modified = modified }
|
|
func (iv *ImageViewBox) IsLoaded() bool { return iv.bmp != nil }
|
|
func (iv *ImageViewBox) AddMode() bool { return iv.add }
|
|
func (iv *ImageViewBox) SetAddMode(add bool) { iv.add = add }
|
|
func (iv *ImageViewBox) HasSelected() bool { return iv.selBox != nil && iv.bmp != nil }
|
|
|
|
func (iv *ImageViewBox) wasModified() {
|
|
iv.modified = true
|
|
iv.onModify.Fire(NewEvent(iv, nil))
|
|
}
|
|
|
|
func (iv *ImageViewBox) DeleteSelected() {
|
|
if iv.selBox != nil {
|
|
for i, b := range iv.Boxes {
|
|
if b == iv.selBox {
|
|
iv.Boxes = append(iv.Boxes[:i], iv.Boxes[i+1:]...)
|
|
iv.selBox = nil
|
|
iv.Invalidate(true)
|
|
iv.wasModified()
|
|
iv.onSelectedChange.Fire(NewEvent(iv, nil))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (iv *ImageViewBox) NameSelected() string {
|
|
if iv.selBox != nil {
|
|
return iv.selBox.Name
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (iv *ImageViewBox) SetNameSelected(name string) {
|
|
if iv.selBox != nil {
|
|
iv.selBox.Name = name
|
|
iv.wasModified()
|
|
}
|
|
}
|
|
|
|
func (iv *ImageViewBox) TypeSelected() int {
|
|
if iv.selBox != nil {
|
|
return iv.selBox.Type
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (iv *ImageViewBox) SetTypeSelected(typ int) {
|
|
if iv.selBox != nil {
|
|
iv.selBox.Type = typ
|
|
iv.wasModified()
|
|
}
|
|
}
|
|
|
|
func (ib *ImageViewBox) updateHighlight(x, y int) bool {
|
|
var changed bool
|
|
for _, b := range ib.Boxes {
|
|
under := x >= b.X && y >= b.Y && x <= b.X2 && y <= b.Y2
|
|
if b.underMouse != under {
|
|
changed = true
|
|
}
|
|
b.underMouse = under
|
|
/*if sel {
|
|
break // allow only one to be underMouse
|
|
}*/
|
|
}
|
|
return changed
|
|
}
|
|
|
|
func (ib *ImageViewBox) isUnderMouse(x, y int) *ImageBox {
|
|
for _, b := range ib.Boxes {
|
|
if x >= b.X && y >= b.Y && x <= b.X2 && y <= b.Y2 {
|
|
return b
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ib *ImageViewBox) getCursor(x, y int) uint16 {
|
|
for _, b := range ib.Boxes {
|
|
switch d := ib.resizingDirection(b, x, y); d {
|
|
case DirY, DirY2:
|
|
return w32.IDC_SIZENS
|
|
case DirX, DirX2:
|
|
return w32.IDC_SIZEWE
|
|
}
|
|
// w32.IDC_SIZEALL or w32.IDC_SIZE for resize
|
|
}
|
|
return w32.IDC_ARROW
|
|
}
|
|
|
|
func (ib *ImageViewBox) resizingDirection(b *ImageBox, x, y int) direction {
|
|
if b == nil {
|
|
return DirNone
|
|
}
|
|
switch {
|
|
case b.X == x || b.X == x-1 || b.X == x+1:
|
|
return DirX
|
|
case b.X2 == x || b.X2 == x-1 || b.X2 == x+1:
|
|
return DirX2
|
|
case b.Y == y || b.Y == y-1 || b.Y == y+1:
|
|
return DirY
|
|
case b.Y2 == y || b.Y2 == y-1 || b.Y2 == y+1:
|
|
return DirY2
|
|
}
|
|
return DirNone
|
|
}
|
|
|
|
func (ib *ImageViewBox) resizeToDirection(b *ImageBox, x, y int) {
|
|
switch ib.resize {
|
|
case DirX:
|
|
b.X = x
|
|
case DirY:
|
|
b.Y = y
|
|
case DirX2:
|
|
b.X2 = x
|
|
case DirY2:
|
|
b.Y2 = y
|
|
}
|
|
}
|
|
|
|
func (ib *ImageViewBox) drag(b *ImageBox, x, y int) {
|
|
w, h := b.X2-b.X, b.Y2-b.Y
|
|
|
|
nx := ib.dragStartX - b.X
|
|
ny := ib.dragStartY - b.Y
|
|
|
|
b.X = x - nx
|
|
b.Y = y - ny
|
|
b.X2 = b.X + w
|
|
b.Y2 = b.Y + h
|
|
|
|
ib.dragStartX, ib.dragStartY = x, y
|
|
}
|
|
|
|
func (iv *ImageViewBox) DrawImageFile(filepath string) (err error) {
|
|
iv.bmp, err = NewBitmapFromFile(filepath, RGB(255, 255, 0))
|
|
iv.selBox = nil
|
|
iv.modified = false
|
|
iv.onSelectedChange.Fire(NewEvent(iv, nil))
|
|
iv.onModify.Fire(NewEvent(iv, nil))
|
|
return
|
|
}
|
|
|
|
func (iv *ImageViewBox) DrawImage(bmp *Bitmap) {
|
|
iv.bmp = bmp
|
|
iv.selBox = nil
|
|
iv.modified = false
|
|
iv.onSelectedChange.Fire(NewEvent(iv, nil))
|
|
iv.onModify.Fire(NewEvent(iv, nil))
|
|
}
|
|
|
|
func (iv *ImageViewBox) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
|
|
switch msg {
|
|
case w32.WM_SIZE, w32.WM_SIZING:
|
|
iv.Invalidate(true)
|
|
|
|
case w32.WM_ERASEBKGND:
|
|
return 1 // important
|
|
|
|
case w32.WM_CREATE:
|
|
internalTrackMouseEvent(iv.hwnd)
|
|
|
|
case w32.WM_PAINT:
|
|
if iv.bmp != nil {
|
|
canvas := NewCanvasFromHwnd(iv.hwnd)
|
|
defer canvas.Dispose()
|
|
iv.SetSize(iv.bmp.Size())
|
|
canvas.DrawBitmap(iv.bmp, 0, 0)
|
|
|
|
for _, b := range iv.Boxes {
|
|
// old code used NewSystemColorBrush(w32.COLOR_BTNFACE) w32.COLOR_WINDOW
|
|
pen := ImageBoxPen
|
|
if b.underMouse {
|
|
pen = ImageBoxHiPen
|
|
}
|
|
canvas.DrawRect(b.Rect(), pen)
|
|
|
|
if b == iv.selBox {
|
|
x1 := []int{b.X, b.X2, b.X2, b.X}
|
|
y1 := []int{b.Y, b.Y, b.Y2, b.Y2}
|
|
|
|
for i := 0; i < len(x1); i++ {
|
|
r := NewRect(x1[i]-2, y1[i]-2, x1[i]+2, y1[i]+2)
|
|
canvas.DrawFillRect(r, ImageBoxMarkPen, ImageBoxMarkBrush)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
case w32.WM_MOUSEMOVE:
|
|
x, y := genPoint(lparam)
|
|
|
|
if iv.dragBox != nil {
|
|
if iv.resize == DirNone {
|
|
iv.drag(iv.dragBox, x, y)
|
|
iv.wasModified()
|
|
} else {
|
|
iv.resizeToDirection(iv.dragBox, x, y)
|
|
iv.wasModified()
|
|
}
|
|
iv.Invalidate(true)
|
|
|
|
} else {
|
|
if !iv.add {
|
|
w32.SetCursor(w32.LoadCursorWithResourceID(0, iv.getCursor(x, y)))
|
|
}
|
|
// do not call repaint if underMouse item did not change.
|
|
if iv.updateHighlight(x, y) {
|
|
iv.Invalidate(true)
|
|
}
|
|
}
|
|
|
|
if iv.mouseLeft {
|
|
internalTrackMouseEvent(iv.hwnd)
|
|
iv.mouseLeft = false
|
|
}
|
|
|
|
case w32.WM_MOUSELEAVE:
|
|
iv.dragBox = nil
|
|
iv.mouseLeft = true
|
|
iv.updateHighlight(-1, -1)
|
|
iv.Invalidate(true)
|
|
|
|
case w32.WM_LBUTTONUP:
|
|
iv.dragBox = nil
|
|
|
|
case w32.WM_LBUTTONDOWN:
|
|
x, y := genPoint(lparam)
|
|
if iv.add {
|
|
now := time.Now()
|
|
s := fmt.Sprintf("field%s", now.Format("020405"))
|
|
b := &ImageBox{Name: s, underMouse: true, X: x, Y: y, X2: x + 150, Y2: y + 30}
|
|
iv.Boxes = append(iv.Boxes, b)
|
|
iv.selBox = b
|
|
iv.wasModified()
|
|
iv.onAdd.Fire(NewEvent(iv, nil))
|
|
} else {
|
|
iv.dragBox = iv.isUnderMouse(x, y)
|
|
iv.selBox = iv.dragBox
|
|
iv.dragStartX, iv.dragStartY = x, y
|
|
iv.resize = iv.resizingDirection(iv.dragBox, x, y)
|
|
}
|
|
iv.Invalidate(true)
|
|
iv.onSelectedChange.Fire(NewEvent(iv, nil))
|
|
|
|
case w32.WM_RBUTTONDOWN:
|
|
|
|
}
|
|
return w32.DefWindowProc(iv.hwnd, msg, wparam, lparam)
|
|
}
|