| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- // Package widget defines the UI widgets within the Fyne toolkit.
- package widget // import "fyne.io/fyne/v2/widget"
- import (
- "sync"
- "fyne.io/fyne/v2"
- "fyne.io/fyne/v2/canvas"
- "fyne.io/fyne/v2/internal/cache"
- internalWidget "fyne.io/fyne/v2/internal/widget"
- )
- // BaseWidget provides a helper that handles basic widget behaviours.
- type BaseWidget struct {
- size fyne.Size
- position fyne.Position
- Hidden bool
- impl fyne.Widget
- propertyLock sync.RWMutex
- }
- // ExtendBaseWidget is used by an extending widget to make use of BaseWidget functionality.
- func (w *BaseWidget) ExtendBaseWidget(wid fyne.Widget) {
- impl := w.super()
- if impl != nil {
- return
- }
- w.propertyLock.Lock()
- defer w.propertyLock.Unlock()
- w.impl = wid
- }
- // Size gets the current size of this widget.
- func (w *BaseWidget) Size() fyne.Size {
- w.propertyLock.RLock()
- defer w.propertyLock.RUnlock()
- return w.size
- }
- // Resize sets a new size for a widget.
- // Note this should not be used if the widget is being managed by a Layout within a Container.
- func (w *BaseWidget) Resize(size fyne.Size) {
- w.propertyLock.RLock()
- baseSize := w.size
- impl := w.impl
- w.propertyLock.RUnlock()
- if baseSize == size {
- return
- }
- w.propertyLock.Lock()
- w.size = size
- w.propertyLock.Unlock()
- if impl == nil {
- return
- }
- cache.Renderer(impl).Layout(size)
- }
- // Position gets the current position of this widget, relative to its parent.
- func (w *BaseWidget) Position() fyne.Position {
- w.propertyLock.RLock()
- defer w.propertyLock.RUnlock()
- return w.position
- }
- // Move the widget to a new position, relative to its parent.
- // Note this should not be used if the widget is being managed by a Layout within a Container.
- func (w *BaseWidget) Move(pos fyne.Position) {
- w.propertyLock.Lock()
- w.position = pos
- w.propertyLock.Unlock()
- internalWidget.Repaint(w.super())
- }
- // MinSize for the widget - it should never be resized below this value.
- func (w *BaseWidget) MinSize() fyne.Size {
- impl := w.super()
- r := cache.Renderer(impl)
- if r == nil {
- return fyne.NewSize(0, 0)
- }
- return r.MinSize()
- }
- // Visible returns whether or not this widget should be visible.
- // Note that this may not mean it is currently visible if a parent has been hidden.
- func (w *BaseWidget) Visible() bool {
- w.propertyLock.RLock()
- defer w.propertyLock.RUnlock()
- return !w.Hidden
- }
- // Show this widget so it becomes visible
- func (w *BaseWidget) Show() {
- if w.Visible() {
- return
- }
- w.setFieldsAndRefresh(func() {
- w.Hidden = false
- })
- }
- // Hide this widget so it is no longer visible
- func (w *BaseWidget) Hide() {
- if !w.Visible() {
- return
- }
- w.propertyLock.Lock()
- w.Hidden = true
- impl := w.impl
- w.propertyLock.Unlock()
- if impl == nil {
- return
- }
- canvas.Refresh(impl)
- }
- // Refresh causes this widget to be redrawn in it's current state
- func (w *BaseWidget) Refresh() {
- impl := w.super()
- if impl == nil {
- return
- }
- render := cache.Renderer(impl)
- render.Refresh()
- }
- // setFieldsAndRefresh helps to make changes to a widget that should be followed by a refresh.
- // This method is a guaranteed thread-safe way of directly manipulating widget fields.
- func (w *BaseWidget) setFieldsAndRefresh(f func()) {
- w.propertyLock.Lock()
- f()
- impl := w.impl
- w.propertyLock.Unlock()
- if impl == nil {
- return
- }
- impl.Refresh()
- }
- // super will return the actual object that this represents.
- // If extended then this is the extending widget, otherwise it is nil.
- func (w *BaseWidget) super() fyne.Widget {
- w.propertyLock.RLock()
- impl := w.impl
- w.propertyLock.RUnlock()
- return impl
- }
- // DisableableWidget describes an extension to BaseWidget which can be disabled.
- // Disabled widgets should have a visually distinct style when disabled, normally using theme.DisabledButtonColor.
- type DisableableWidget struct {
- BaseWidget
- disabled bool
- }
- // Enable this widget, updating any style or features appropriately.
- func (w *DisableableWidget) Enable() {
- if !w.Disabled() {
- return
- }
- w.setFieldsAndRefresh(func() {
- w.disabled = false
- })
- }
- // Disable this widget so that it cannot be interacted with, updating any style appropriately.
- func (w *DisableableWidget) Disable() {
- if w.Disabled() {
- return
- }
- w.setFieldsAndRefresh(func() {
- w.disabled = true
- })
- }
- // Disabled returns true if this widget is currently disabled or false if it can currently be interacted with.
- func (w *DisableableWidget) Disabled() bool {
- w.propertyLock.RLock()
- defer w.propertyLock.RUnlock()
- return w.disabled
- }
- // NewSimpleRenderer creates a new SimpleRenderer to render a widget using a
- // single fyne.CanvasObject.
- //
- // Since: 2.1
- func NewSimpleRenderer(object fyne.CanvasObject) fyne.WidgetRenderer {
- return internalWidget.NewSimpleRenderer(object)
- }
|