fckeuspy-go/vendor/fyne.io/fyne/v2/dialog/base.go

260 lines
6.2 KiB
Go

// Package dialog defines standard dialog windows for application GUIs.
package dialog // import "fyne.io/fyne/v2/dialog"
import (
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
col "fyne.io/fyne/v2/internal/color"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
const (
padWidth = 32
padHeight = 16
)
// Dialog is the common API for any dialog window with a single dismiss button
type Dialog interface {
Show()
Hide()
SetDismissText(label string)
SetOnClosed(closed func())
Refresh()
Resize(size fyne.Size)
// MinSize returns the size that this dialog should not shrink below.
//
// Since: 2.1
MinSize() fyne.Size
// Dismiss instructs the dialog to close without any affirmative action.
//
// Since: 2.6
Dismiss()
}
// Declare conformity to Dialog interface
var _ Dialog = (*dialog)(nil)
type dialog struct {
callback func(bool)
title string
icon fyne.Resource
desiredSize fyne.Size
win *widget.PopUp
content fyne.CanvasObject
dismiss *widget.Button
parent fyne.Window
// allows derived dialogs to inject logic that runs before Show()
beforeShowHook func()
}
func (d *dialog) Dismiss() {
d.Hide()
}
func (d *dialog) Hide() {
d.hideWithResponse(false)
}
// MinSize returns the size that this dialog should not shrink below.
//
// Since: 2.1
func (d *dialog) MinSize() fyne.Size {
return d.win.MinSize()
}
func (d *dialog) Show() {
if d.beforeShowHook != nil {
d.beforeShowHook()
}
if !d.desiredSize.IsZero() {
d.win.Resize(d.desiredSize)
}
d.win.Show()
}
func (d *dialog) Refresh() {
d.win.Refresh()
}
// Resize dialog, call this function after dialog show
func (d *dialog) Resize(size fyne.Size) {
d.desiredSize = size
if d.win != nil { // could be called before popup is created!
d.win.Resize(size)
}
}
// SetDismissText allows custom text to be set in the dismiss button
// This is a no-op for dialogs without dismiss buttons.
func (d *dialog) SetDismissText(label string) {
if d.dismiss == nil {
return
}
d.dismiss.SetText(label)
d.win.Refresh()
}
// SetOnClosed allows to set a callback function that is called when
// the dialog is closed
func (d *dialog) SetOnClosed(closed func()) {
// if there is already a callback set, remember it and call both
originalCallback := d.callback
d.callback = func(response bool) {
if originalCallback != nil {
originalCallback(response)
}
closed()
}
}
func (d *dialog) hideWithResponse(resp bool) {
d.win.Hide()
if d.callback != nil {
d.callback(resp)
}
}
func (d *dialog) create(buttons fyne.CanvasObject) {
label := widget.NewLabelWithStyle(d.title, fyne.TextAlignLeading, fyne.TextStyle{Bold: true})
var image fyne.CanvasObject
if d.icon != nil {
image = &canvas.Image{Resource: d.icon}
} else {
image = &layout.Spacer{}
}
content := container.New(&dialogLayout{d: d},
image,
newThemedBackground(),
d.content,
buttons,
label,
)
d.win = widget.NewModalPopUp(content, d.parent.Canvas())
}
func (d *dialog) setButtons(buttons fyne.CanvasObject) {
d.win.Content.(*fyne.Container).Objects[3] = buttons
d.win.Refresh()
}
func (d *dialog) setIcon(icon fyne.Resource) {
if icon == nil {
d.win.Content.(*fyne.Container).Objects[0] = &layout.Spacer{}
d.win.Refresh()
return
}
d.win.Content.(*fyne.Container).Objects[0] = &canvas.Image{Resource: icon}
d.win.Refresh()
}
// The method .create() needs to be called before the dialog can be shown.
func newDialog(title, message string, icon fyne.Resource, callback func(bool), parent fyne.Window) *dialog {
d := &dialog{content: newCenterWrappedLabel(message), title: title, icon: icon, parent: parent}
d.callback = callback
return d
}
// ===============================================================
// ThemedBackground
// ===============================================================
type themedBackground struct {
widget.BaseWidget
}
func newThemedBackground() *themedBackground {
t := &themedBackground{}
t.ExtendBaseWidget(t)
return t
}
func (t *themedBackground) CreateRenderer() fyne.WidgetRenderer {
t.ExtendBaseWidget(t)
rect := canvas.NewRectangle(theme.Color(theme.ColorNameOverlayBackground))
return &themedBackgroundRenderer{rect, []fyne.CanvasObject{rect}}
}
type themedBackgroundRenderer struct {
rect *canvas.Rectangle
objects []fyne.CanvasObject
}
func (renderer *themedBackgroundRenderer) Destroy() {
}
func (renderer *themedBackgroundRenderer) Layout(size fyne.Size) {
renderer.rect.Resize(size)
}
func (renderer *themedBackgroundRenderer) MinSize() fyne.Size {
return renderer.rect.MinSize()
}
func (renderer *themedBackgroundRenderer) Objects() []fyne.CanvasObject {
return renderer.objects
}
func (renderer *themedBackgroundRenderer) Refresh() {
r, g, b, _ := col.ToNRGBA(theme.Color(theme.ColorNameOverlayBackground))
bg := &color.NRGBA{R: uint8(r), G: uint8(g), B: uint8(b), A: 230}
renderer.rect.FillColor = bg
}
// ===============================================================
// DialogLayout
// ===============================================================
type dialogLayout struct {
d *dialog
}
func (l *dialogLayout) Layout(obj []fyne.CanvasObject, size fyne.Size) {
btnMin := obj[3].MinSize()
labelMin := obj[4].MinSize()
// icon
iconHeight := padHeight*2 + labelMin.Height*2 - theme.Padding()
obj[0].Resize(fyne.NewSize(iconHeight, iconHeight))
obj[0].Move(fyne.NewPos(size.Width-iconHeight+theme.Padding(), -theme.Padding()))
// background
obj[1].Move(fyne.NewPos(0, 0))
obj[1].Resize(size)
// content
contentStart := obj[4].Position().Y + labelMin.Height + padHeight
contentEnd := obj[3].Position().Y - theme.Padding()
obj[2].Move(fyne.NewPos(padWidth/2, labelMin.Height+padHeight))
obj[2].Resize(fyne.NewSize(size.Width-padWidth, contentEnd-contentStart))
// buttons
obj[3].Resize(btnMin)
obj[3].Move(fyne.NewPos(size.Width/2-(btnMin.Width/2), size.Height-padHeight-btnMin.Height))
}
func (l *dialogLayout) MinSize(obj []fyne.CanvasObject) fyne.Size {
contentMin := obj[2].MinSize()
btnMin := obj[3].MinSize()
labelMin := obj[4].MinSize()
width := fyne.Max(fyne.Max(contentMin.Width, btnMin.Width), labelMin.Width) + padWidth
height := contentMin.Height + btnMin.Height + labelMin.Height + theme.Padding() + padHeight*2
return fyne.NewSize(width, height)
}