Added various widgets
This commit is contained in:
parent
9b3d5df603
commit
8befd14d13
@ -368,7 +368,7 @@ func (d *FormDialog) Show(parent ...fyne.Window) {
|
||||
d.items = d.itemsFn()
|
||||
|
||||
d.concreteDialog.OnShow()
|
||||
d.dlg = dialog.NewForm(
|
||||
frm := dialog.NewForm(
|
||||
d.concreteDialog.Title(),
|
||||
d.confirmLabel,
|
||||
d.dismissLabel,
|
||||
@ -376,6 +376,7 @@ func (d *FormDialog) Show(parent ...fyne.Window) {
|
||||
d.concreteDialog.OnClose,
|
||||
d.window,
|
||||
)
|
||||
d.dlg = frm
|
||||
d.dlg.Show()
|
||||
d.dlg.Resize(fyne.NewSize(640, 480))
|
||||
if d.focusItem != nil {
|
||||
|
@ -55,15 +55,17 @@ type Element struct {
|
||||
Disabled bool `yaml:"disabled"`
|
||||
Hidden bool `yaml:"hidden"`
|
||||
|
||||
// Properties shared by most widgets
|
||||
Placeholder string `yaml:"placeholder"`
|
||||
PlaceholderLocalized bool `yaml:"placeholderLocalized"`
|
||||
|
||||
// Calendar Properties
|
||||
Time *string `yaml:"time"`
|
||||
TimeFormat *string `yaml:"timeFormat"`
|
||||
|
||||
// Entry Properties
|
||||
MultiLine bool `yaml:"multiLine"`
|
||||
Placeholder string `yaml:"placeholder"`
|
||||
PlaceholderLocalized bool `yaml:"placeholderLocalized"`
|
||||
Validator string `yaml:"validator"`
|
||||
MultiLine bool `yaml:"multiLine"`
|
||||
Validator string `yaml:"validator"`
|
||||
|
||||
// List Properties
|
||||
ItemTemplate string `yaml:"itemTemplate"`
|
||||
@ -73,6 +75,10 @@ type Element struct {
|
||||
// Check Properties
|
||||
Checked bool `yaml:"checked"`
|
||||
|
||||
// Select Properties
|
||||
SelectOptionsBinding string `yaml:"selectOptionsBinding"`
|
||||
SelectOptions []string `yaml:"selectOptions"`
|
||||
|
||||
// Spacer Properties
|
||||
FixHorizontal bool `yaml:"fixHorizontal"`
|
||||
FixVertical bool `yaml:"fixVertical"`
|
||||
@ -85,6 +91,7 @@ type Element struct {
|
||||
OnSelected string `yaml:"onSelected"`
|
||||
OnUnselected string `yaml:"onUnselected"`
|
||||
OnDateSelected string `yaml:"onDateSelected"`
|
||||
OnOptionSelected string `yaml:"onOptionSelected"`
|
||||
OnValidationChanged string `yaml:"onValidationChanged"`
|
||||
}
|
||||
|
||||
|
@ -219,6 +219,7 @@ func (l Layout) buildFormLayout(
|
||||
|
||||
children = append(children, label, field)
|
||||
}
|
||||
|
||||
c = container.New(layout.NewFormLayout(), children...)
|
||||
return
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ type ListItemHandlerFn func(widget.ListItemID)
|
||||
type ClickHandlerFn func()
|
||||
type CheckHandlerFn func(bool)
|
||||
type DateSelectedHandlerFn func(time.Time)
|
||||
type OptionSelectedHandlerFn func(string)
|
||||
type ValidationChangedHandlerFn func(error)
|
||||
|
||||
type UIElement struct {
|
||||
@ -48,6 +49,7 @@ type ScreenHandler interface {
|
||||
GetOnClickedHandler(string) ClickHandlerFn
|
||||
GetOnCheckChangedHandler(string) CheckHandlerFn
|
||||
GetOnDateSelectedHandler(string) DateSelectedHandlerFn
|
||||
GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn
|
||||
GetOnValidationChangedHandler(string) ValidationChangedHandlerFn
|
||||
}
|
||||
|
||||
@ -195,6 +197,10 @@ func (*TemplateScreenHandler) GetOnDateSelectedHandler(string) DateSelectedHandl
|
||||
return func(time.Time) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetOnOptionSelectedHandler(string) OptionSelectedHandlerFn {
|
||||
return func(string) {}
|
||||
}
|
||||
|
||||
func (*TemplateScreenHandler) GetOnValidationChangedHandler(string) ValidationChangedHandlerFn {
|
||||
return func(error) {}
|
||||
}
|
||||
|
112
screen/widget.go
112
screen/widget.go
@ -55,6 +55,8 @@ const (
|
||||
// - onChanged: The function to call when the checkbox is changed
|
||||
Check Widget = "Check"
|
||||
|
||||
DateEntry Widget = "DateEntry"
|
||||
|
||||
// Entry Widget
|
||||
//
|
||||
// Available yaml options:
|
||||
@ -165,6 +167,12 @@ const (
|
||||
// - onUnselect: The on unselect function for the list
|
||||
List Widget = "List"
|
||||
|
||||
// Select Widget
|
||||
Select Widget = "Select"
|
||||
|
||||
// SelectEntry Widget
|
||||
SelectEntry Widget = "SelectEntry"
|
||||
|
||||
// Separator Widget
|
||||
Separator Widget = "Separator"
|
||||
|
||||
@ -207,6 +215,8 @@ func (w Widget) Build(
|
||||
widget, err = w.buildCalendarWidget(e, s)
|
||||
case Check:
|
||||
widget, err = w.buildCheckWidget(e, s)
|
||||
case DateEntry:
|
||||
widget, err = w.buildDateEntryWidget(e, s)
|
||||
case Entry:
|
||||
widget, err = w.buildEntryWidget(e, s)
|
||||
case H1, H2, H3, H4, H5, H6:
|
||||
@ -217,6 +227,10 @@ func (w Widget) Build(
|
||||
widget, err = w.buildLabelWidget(e, s)
|
||||
case List:
|
||||
widget, err = w.buildListWidget(e, s)
|
||||
case Select:
|
||||
widget, err = w.buildSelectWidget(e, s)
|
||||
case SelectEntry:
|
||||
widget, err = w.buildSelectEntryWidget(e, s)
|
||||
case Separator:
|
||||
widget, err = w.buildSeparatorWidget(e, s)
|
||||
case Spacer:
|
||||
@ -317,6 +331,23 @@ func (w Widget) buildCheckWidget(
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildDateEntryWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
ent := uiwidget.NewDateEntry()
|
||||
|
||||
if e.OnDateSelected != "" {
|
||||
ent.OnDateChanged = s.GetOnDateSelectedHandler(e.OnDateSelected)
|
||||
}
|
||||
|
||||
if e.Disabled {
|
||||
ent.Disable()
|
||||
}
|
||||
c = ent
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildEntryWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
@ -452,6 +483,82 @@ func (w Widget) buildListWidget(
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildSelectWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var slc *widget.Select
|
||||
var options []string
|
||||
|
||||
if e.Binding != "" {
|
||||
if lst, ok := s.GetBinding(e.SelectOptionsBinding).(binding.StringList); ok {
|
||||
options, _ = lst.Get()
|
||||
}
|
||||
} else {
|
||||
options = e.SelectOptions
|
||||
}
|
||||
|
||||
slc = widget.NewSelect(options,
|
||||
s.GetOnOptionSelectedHandler(e.OnOptionSelected))
|
||||
slc.PlaceHolder = e.Placeholder
|
||||
|
||||
for opt, val := range e.Options {
|
||||
switch opt {
|
||||
case "alignment":
|
||||
slc.Alignment = getTextAlignment(val)
|
||||
}
|
||||
}
|
||||
|
||||
if e.Disabled {
|
||||
slc.Disable()
|
||||
}
|
||||
c = slc
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildSelectEntryWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var slc *widget.SelectEntry
|
||||
var options []string
|
||||
|
||||
if e.SelectOptionsBinding != "" {
|
||||
if lst, ok := s.GetBinding(e.SelectOptionsBinding).(binding.StringList); ok {
|
||||
options, _ = lst.Get()
|
||||
lst.AddListener(binding.NewDataListener(func() {
|
||||
options, _ = lst.Get()
|
||||
if slc != nil {
|
||||
slc.SetOptions(options)
|
||||
}
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
options = e.SelectOptions
|
||||
}
|
||||
|
||||
slc = widget.NewSelectEntry(options)
|
||||
|
||||
if e.Binding != "" {
|
||||
slc.Bind(s.GetBinding(e.Binding).(binding.String))
|
||||
} else {
|
||||
slc.Text = e.Text
|
||||
}
|
||||
slc.PlaceHolder = e.Placeholder
|
||||
if e.Validator != "" {
|
||||
slc.Validator = s.GetValidator(e.Validator)
|
||||
}
|
||||
if e.OnValidationChanged != "" {
|
||||
slc.SetOnValidationChanged(s.GetOnValidationChangedHandler(e.OnValidationChanged))
|
||||
}
|
||||
|
||||
if e.Disabled {
|
||||
slc.Disable()
|
||||
}
|
||||
c = slc
|
||||
return
|
||||
}
|
||||
|
||||
func (w Widget) buildSeparatorWidget(
|
||||
_ *Element,
|
||||
_ ScreenHandler,
|
||||
@ -477,7 +584,12 @@ func (w Widget) buildUpDownLabelWidget(
|
||||
e *Element,
|
||||
s ScreenHandler,
|
||||
) (c fyne.CanvasObject, err error) {
|
||||
var minSize *fyne.Size
|
||||
if e.MinSize != nil {
|
||||
minSize = &fyne.Size{Width: e.MinSize.Width, Height: e.MinSize.Height}
|
||||
}
|
||||
btn := uiwidget.NewUpDownLabelWithData(
|
||||
minSize,
|
||||
s.GetBinding(e.Binding).(binding.String),
|
||||
s.GetOnClickedHandler(e.OnUpClicked),
|
||||
s.GetOnClickedHandler(e.OnDownClicked))
|
||||
|
@ -40,6 +40,7 @@ type ScreenHandler struct {
|
||||
onClickedHandlers map[string]screen.ClickHandlerFn
|
||||
onCheckChangedHandlers map[string]screen.CheckHandlerFn
|
||||
onDateSelectedHandlers map[string]screen.DateSelectedHandlerFn
|
||||
onOptionSelectedHandlers map[string]screen.OptionSelectedHandlerFn
|
||||
onValidationChangedHandlers map[string]screen.ValidationChangedHandlerFn
|
||||
}
|
||||
|
||||
@ -82,6 +83,7 @@ func NewScreenHandler(
|
||||
h.onClickedHandlers = make(map[string]screen.ClickHandlerFn)
|
||||
h.onCheckChangedHandlers = make(map[string]screen.CheckHandlerFn)
|
||||
h.onDateSelectedHandlers = make(map[string]screen.DateSelectedHandlerFn)
|
||||
h.onOptionSelectedHandlers = make(map[string]screen.OptionSelectedHandlerFn)
|
||||
h.onValidationChangedHandlers = make(map[string]screen.ValidationChangedHandlerFn)
|
||||
return
|
||||
}
|
||||
@ -202,6 +204,17 @@ func (h *ScreenHandler) RegisterOnDateSelectedHandler(
|
||||
h.onDateSelectedHandlers[name] = fn
|
||||
}
|
||||
|
||||
// RegisterOnOptionSelectedHandler registers a OnOptionSelectedHandler with the ScreenHandler.
|
||||
//
|
||||
// Use this function to register the handler functions used in the screen
|
||||
// definition.
|
||||
func (h *ScreenHandler) RegisterOnOptionSelectedHandler(
|
||||
name string,
|
||||
fn screen.OptionSelectedHandlerFn,
|
||||
) {
|
||||
h.onOptionSelectedHandlers[name] = fn
|
||||
}
|
||||
|
||||
// RegisterOnValidationChangedHandler registers a OnValidationChangedHandler with the ScreenHandler.
|
||||
//
|
||||
// Use this function to register the handler functions used in the screen
|
||||
@ -245,6 +258,42 @@ func (h *ScreenHandler) GetElement(id string) *screen.UIElement {
|
||||
return elem
|
||||
}
|
||||
|
||||
func (h *ScreenHandler) ReplaceElementObject(
|
||||
containerId string,
|
||||
id string,
|
||||
newDecorator fyne.CanvasObject,
|
||||
newObject fyne.CanvasObject,
|
||||
) {
|
||||
containerElement := h.GetElement(containerId)
|
||||
if containerElement == nil {
|
||||
return
|
||||
}
|
||||
containerObj := containerElement.Object.(*fyne.Container)
|
||||
|
||||
element := h.GetElement(id)
|
||||
if element == nil {
|
||||
return
|
||||
}
|
||||
decorator := element.Decorator
|
||||
|
||||
allObjs := containerObj.Objects
|
||||
replaced := false
|
||||
for i, obj := range allObjs {
|
||||
if obj == decorator {
|
||||
allObjs[i] = newDecorator
|
||||
replaced = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if replaced {
|
||||
h.exportedElements[id].Decorator = newDecorator
|
||||
h.exportedElements[id].Object = newObject
|
||||
}
|
||||
|
||||
containerObj.Refresh()
|
||||
}
|
||||
|
||||
// GetLocalizer returns the i18n.Localizer used for localization.
|
||||
func (h *ScreenHandler) GetLocalizer() *i18n.Localizer {
|
||||
return h.localizer
|
||||
@ -354,6 +403,15 @@ func (h *ScreenHandler) GetOnDateSelectedHandler(name string) screen.DateSelecte
|
||||
return fn
|
||||
}
|
||||
|
||||
func (h *ScreenHandler) GetOnOptionSelectedHandler(name string) screen.OptionSelectedHandlerFn {
|
||||
fn, ok := h.onOptionSelectedHandlers[name]
|
||||
if !ok {
|
||||
log.Printf("option selected handler %s not found", name)
|
||||
return nil
|
||||
}
|
||||
return fn
|
||||
}
|
||||
|
||||
// GetOnValidationChangedHandler returns the OnValidationChangedHandler with the given name.
|
||||
func (h *ScreenHandler) GetOnValidationChangedHandler(name string) screen.ValidationChangedHandlerFn {
|
||||
fn, ok := h.onValidationChangedHandlers[name]
|
||||
|
131
uiwidget/dateentry.go
Normal file
131
uiwidget/dateentry.go
Normal file
@ -0,0 +1,131 @@
|
||||
package uiwidget
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
|
||||
xwidget "fyne.io/x/fyne/widget"
|
||||
)
|
||||
|
||||
type DateEntry struct {
|
||||
widget.Entry
|
||||
calendar *xwidget.Calendar
|
||||
popUp *widget.PopUp
|
||||
|
||||
OnDateChanged func(time.Time)
|
||||
|
||||
date time.Time
|
||||
}
|
||||
|
||||
func NewDateEntry() *DateEntry {
|
||||
e := &DateEntry{}
|
||||
e.Validator = func(s string) error {
|
||||
_, err := time.Parse("02/01/2006", s)
|
||||
return err
|
||||
}
|
||||
e.OnChanged = func(s string) {
|
||||
if e.Validate() != nil {
|
||||
if e.OnDateChanged != nil {
|
||||
time, _ := time.Parse("02/01/2006", s)
|
||||
e.OnDateChanged(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
e.ExtendBaseWidget(e)
|
||||
e.SetDate(time.Now())
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *DateEntry) CreateRenderer() fyne.WidgetRenderer {
|
||||
e.ExtendBaseWidget(e)
|
||||
if e.ActionItem == nil {
|
||||
e.ActionItem = e.setupDropdown()
|
||||
if e.Disabled() {
|
||||
e.ActionItem.(fyne.Disableable).Disable()
|
||||
}
|
||||
}
|
||||
return e.Entry.CreateRenderer()
|
||||
}
|
||||
|
||||
func (e *DateEntry) Enable() {
|
||||
if e.ActionItem != nil {
|
||||
e.ActionItem.(fyne.Disableable).Enable()
|
||||
}
|
||||
e.Entry.Enable()
|
||||
}
|
||||
|
||||
func (e *DateEntry) Disable() {
|
||||
if e.ActionItem != nil {
|
||||
e.ActionItem.(fyne.Disableable).Disable()
|
||||
}
|
||||
e.Entry.Disable()
|
||||
}
|
||||
|
||||
func (e *DateEntry) MinSize() fyne.Size {
|
||||
e.ExtendBaseWidget(e)
|
||||
return e.Entry.MinSize()
|
||||
}
|
||||
|
||||
func (e *DateEntry) Move(pos fyne.Position) {
|
||||
e.Entry.Move(pos)
|
||||
if e.popUp != nil {
|
||||
e.popUp.Move(e.popUpPos())
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DateEntry) Resize(size fyne.Size) {
|
||||
e.Entry.Resize(size)
|
||||
if e.popUp != nil {
|
||||
e.popUp.Resize(fyne.NewSize(size.Width, e.popUp.Size().Height))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DateEntry) SetDate(date time.Time) {
|
||||
e.date = date
|
||||
e.calendar = xwidget.NewCalendar(date, e.onDateSelected)
|
||||
e.SetText(date.Format("02/01/2006"))
|
||||
|
||||
if e.ActionItem == nil {
|
||||
e.ActionItem = e.setupDropdown()
|
||||
if e.Disabled() {
|
||||
e.ActionItem.(fyne.Disableable).Disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DateEntry) GetDate() time.Time {
|
||||
return e.date
|
||||
}
|
||||
|
||||
func (e *DateEntry) popUpPos() fyne.Position {
|
||||
entryPos := fyne.CurrentApp().Driver().AbsolutePositionForObject(e)
|
||||
return entryPos.Add(fyne.NewPos(0, e.Size().Height-theme.InputBorderSize()))
|
||||
}
|
||||
|
||||
func (e *DateEntry) setupDropdown() *widget.Button {
|
||||
dropdownButton := widget.NewButton("", func() {
|
||||
c := fyne.CurrentApp().Driver().CanvasForObject(e)
|
||||
|
||||
e.popUp = widget.NewPopUp(e.calendar, c)
|
||||
e.popUp.ShowAtPosition(e.popUpPos())
|
||||
e.popUp.Resize(
|
||||
fyne.NewSize(
|
||||
float32(math.Max(float64(e.Size().Width), float64(e.popUp.MinSize().Width))),
|
||||
e.popUp.MinSize().Height))
|
||||
})
|
||||
dropdownButton.Importance = widget.LowImportance
|
||||
dropdownButton.SetIcon(theme.MenuDropDownIcon())
|
||||
return dropdownButton
|
||||
}
|
||||
|
||||
func (e *DateEntry) onDateSelected(date time.Time) {
|
||||
e.date = date
|
||||
e.SetText(e.date.Format("02/01/2006"))
|
||||
if e.popUp != nil {
|
||||
e.popUp.Hide()
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/hevanto/ui/uilayout"
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/container"
|
||||
"fyne.io/fyne/v2/data/binding"
|
||||
@ -125,11 +126,11 @@ func NewLabelWithData(data binding.String, opts ...LabelOpts) *widget.Label {
|
||||
//
|
||||
// Returns fyne.CanvasObject: the created widget.
|
||||
func NewUpDownLabelWithData(
|
||||
minSize *fyne.Size,
|
||||
data binding.String,
|
||||
upHandler func(),
|
||||
downHandler func(),
|
||||
) fyne.CanvasObject {
|
||||
c1 := container.NewWithoutLayout()
|
||||
c2 := container.NewWithoutLayout()
|
||||
w := NewWidgetBorder(
|
||||
widget.NewLabelWithData(data),
|
||||
@ -137,15 +138,19 @@ func NewUpDownLabelWithData(
|
||||
bu := widget.NewButtonWithIcon("", theme.MoveUpIcon(), upHandler)
|
||||
bd := widget.NewButtonWithIcon("", theme.MoveDownIcon(), downHandler)
|
||||
w.Resize(fyne.NewSize(100, w.MinSize().Height))
|
||||
c1.Add(w)
|
||||
c2.Move(fyne.NewPos(w.Size().Width, 0))
|
||||
c1.Add(c2)
|
||||
bu.Resize(fyne.NewSize(30, w.Size().Height*0.5))
|
||||
bd.Resize(fyne.NewSize(30, w.Size().Height*0.5))
|
||||
bd.Move(fyne.NewPos(0, w.Size().Height*0.5))
|
||||
c2.Add(bu)
|
||||
c2.Add(bd)
|
||||
return c1
|
||||
|
||||
if minSize == nil {
|
||||
minSize = &fyne.Size{Width: 100, Height: 0}
|
||||
}
|
||||
return container.NewHBox(
|
||||
container.New(uilayout.NewMinSizeLayout(*minSize),
|
||||
w), c2)
|
||||
}
|
||||
|
||||
// NewH creates a RichText widget formatted as a header of the provided level.
|
||||
|
Loading…
Reference in New Issue
Block a user