package container import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/internal/cache" intTheme "fyne.io/fyne/v2/internal/theme" "fyne.io/fyne/v2/widget" ) // ThemeOverride is a container where the child widgets are themed by the specified theme. // Containers will be traversed and all child widgets will reflect the theme in this container. // This should be used sparingly to avoid a jarring user experience. // // Since: 2.5 type ThemeOverride struct { widget.BaseWidget Content fyne.CanvasObject Theme fyne.Theme holder *fyne.Container mobile bool } // NewThemeOverride provides a container where the child widgets are themed by the specified theme. // Containers will be traversed and all child widgets will reflect the theme in this container. // This should be used sparingly to avoid a jarring user experience. // // If the content `obj` of this theme override is a container and items are later added to the container or any // sub-containers ensure that you call `Refresh()` on this `ThemeOverride` to ensure the new items match the theme. // // Since: 2.5 func NewThemeOverride(obj fyne.CanvasObject, th fyne.Theme) *ThemeOverride { t := &ThemeOverride{Content: obj, Theme: th, holder: NewStack(obj)} t.ExtendBaseWidget(t) cache.OverrideTheme(obj, addFeatures(th, t)) obj.Refresh() // required as the widgets passed in could have been initially rendered with default theme return t } func (t *ThemeOverride) CreateRenderer() fyne.WidgetRenderer { cache.OverrideTheme(t.Content, addFeatures(t.Theme, t)) return &overrideRenderer{parent: t, objs: []fyne.CanvasObject{t.holder}} } func (t *ThemeOverride) Refresh() { if t.holder.Objects[0] != t.Content { t.holder.Objects[0] = t.Content t.holder.Refresh() } cache.OverrideTheme(t.Content, addFeatures(t.Theme, t)) t.Content.Refresh() t.BaseWidget.Refresh() } // SetDeviceIsMobile allows a ThemeOverride container to shape the contained widgets as a mobile device. // This will impact containers such as AppTabs and DocTabs, and more in the future, to display a layout // that would automatically be used for a mobile device runtime. // // Since: 2.6 func (t *ThemeOverride) SetDeviceIsMobile(on bool) { t.mobile = on t.BaseWidget.Refresh() } type featureTheme struct { fyne.Theme over *ThemeOverride } func addFeatures(th fyne.Theme, o *ThemeOverride) fyne.Theme { return &featureTheme{Theme: th, over: o} } func (f *featureTheme) Feature(n intTheme.FeatureName) any { if n == intTheme.FeatureNameDeviceIsMobile { return f.over.mobile } return nil } type overrideRenderer struct { parent *ThemeOverride objs []fyne.CanvasObject } func (r *overrideRenderer) Destroy() { } func (r *overrideRenderer) Layout(s fyne.Size) { intTheme.PushRenderingTheme(r.parent.Theme) defer intTheme.PopRenderingTheme() r.parent.holder.Resize(s) } func (r *overrideRenderer) MinSize() fyne.Size { intTheme.PushRenderingTheme(r.parent.Theme) defer intTheme.PopRenderingTheme() return r.parent.Content.MinSize() } func (r *overrideRenderer) Objects() []fyne.CanvasObject { return r.objs } func (r *overrideRenderer) Refresh() { }