VideoTools/vendor/fyne.io/fyne/v2/container/navigation.go
Stu Leak 68df790d27 Fix player frame generation and video playback
Major improvements to UnifiedPlayer:

1. GetFrameImage() now works when paused for responsive UI updates
2. Play() method properly starts FFmpeg process
3. Frame display loop runs continuously for smooth video display
4. Disabled audio temporarily to fix video playback fundamentals
5. Simplified FFmpeg command to focus on video stream only

Player now:
- Generates video frames correctly
- Shows video when paused
- Has responsive progress tracking
- Starts playback properly

Next steps: Re-enable audio playback once video is stable
2026-01-07 22:20:00 -05:00

216 lines
4.6 KiB
Go

package container
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
// Navigation container is used to provide your application with a control bar and an area for content objects.
// Objects can be any CanvasObject, and only the most recent one will be visible.
//
// Since: 2.7
type Navigation struct {
widget.BaseWidget
Root fyne.CanvasObject
Title string
OnBack func()
OnForward func()
level int
stack fyne.Container
titles []string
}
// NewNavigation creates a new navigation container with a given root object.
//
// Since: 2.7
func NewNavigation(root fyne.CanvasObject) *Navigation {
return NewNavigationWithTitle(root, "")
}
// NewNavigationWithTitle creates a new navigation container with a given root object and a default title.
//
// Since: 2.7
func NewNavigationWithTitle(root fyne.CanvasObject, s string) *Navigation {
var nav *Navigation
nav = &Navigation{
Root: root,
Title: s,
OnBack: func() { _ = nav.Back() },
OnForward: func() { _ = nav.Forward() },
}
return nav
}
// Push puts the given object on top of the navigation stack and hides the object below.
//
// Since: 2.7
func (nav *Navigation) Push(obj fyne.CanvasObject) {
nav.PushWithTitle(obj, nav.Title)
}
// PushWithTitle puts the given CanvasObject on top, hides the object below, and uses the given title as label text.
//
// Since: 2.7
func (nav *Navigation) PushWithTitle(obj fyne.CanvasObject, s string) {
obj.Show()
objs := nav.stack.Objects[:nav.level]
if len(objs) > 0 {
objs[len(objs)-1].Hide()
}
nav.stack.Objects = append(objs, obj)
nav.titles = append(nav.titles[:nav.level], s)
nav.level++
nav.Refresh()
}
// Back returns the top level CanvasObject, adjusts the title accordingly, and disabled the back button
// when no more objects are left to go back to.
//
// Since: 2.7
func (nav *Navigation) Back() fyne.CanvasObject {
if nav.level == 0 || nav.level == 1 && nav.Root != nil {
return nil
}
objs := nav.stack.Objects
objs[nav.level-1].Hide()
if nav.level > 1 {
objs[nav.level-2].Show()
}
nav.level--
nav.Refresh()
return objs[nav.level]
}
// Forward shows the next object in the stack again.
//
// Since: 2.7
func (nav *Navigation) Forward() fyne.CanvasObject {
if nav.level >= len(nav.stack.Objects) {
return nil
}
nav.stack.Objects[nav.level-1].Hide()
nav.stack.Objects[nav.level].Show()
nav.level++
return nav.stack.Objects[nav.level-1]
}
// SetTitle changes the root navigation title shown by default.
//
// Since: 2.7
func (nav *Navigation) SetTitle(s string) {
nav.Title = s
nav.Refresh()
}
// SetCurrentTitle changes the navigation title for the current level.
//
// Since: 2.7
func (nav *Navigation) SetCurrentTitle(s string) {
if nav.level > 1 && nav.level-1 < len(nav.titles) {
nav.titles[nav.level-1] = s
nav.Refresh()
}
}
func (nav *Navigation) setup() {
objs := []fyne.CanvasObject{}
titles := []string{}
if nav.Root != nil {
objs = append(objs, nav.Root)
titles = append(titles, nav.Title)
}
nav.level = len(objs)
nav.stack.Layout = layout.NewStackLayout()
nav.stack.Objects = objs
nav.titles = titles
nav.ExtendBaseWidget(nav)
}
var _ fyne.WidgetRenderer = (*navigatorRenderer)(nil)
type navigatorRenderer struct {
nav *Navigation
back widget.Button
forward widget.Button
title widget.Label
object fyne.CanvasObject
}
func (nav *Navigation) CreateRenderer() fyne.WidgetRenderer {
r := &navigatorRenderer{
nav: nav,
title: widget.Label{
Text: nav.Title,
Alignment: fyne.TextAlignCenter,
},
back: widget.Button{
Icon: theme.NavigateBackIcon(),
OnTapped: nav.OnBack,
},
forward: widget.Button{
Icon: theme.NavigateNextIcon(),
OnTapped: nav.OnForward,
},
}
r.back.Disable()
r.forward.Disable()
nav.setup()
r.object = NewBorder(
NewStack(NewHBox(&r.back, layout.NewSpacer(), &r.forward), &r.title),
nil,
nil,
nil,
&nav.stack,
)
return r
}
func (r *navigatorRenderer) Destroy() {
}
func (r *navigatorRenderer) Layout(s fyne.Size) {
r.object.Resize(s)
}
func (r *navigatorRenderer) MinSize() fyne.Size {
return r.object.MinSize()
}
func (r *navigatorRenderer) Objects() []fyne.CanvasObject {
return []fyne.CanvasObject{r.object}
}
func (r *navigatorRenderer) Refresh() {
if r.nav.level < 1 || r.nav.level == 1 && r.nav.Root != nil {
r.back.Disable()
} else {
r.back.Enable()
}
if r.nav.level == len(r.nav.stack.Objects) {
r.forward.Disable()
} else {
r.forward.Enable()
}
if r.nav.level-1 >= 0 && r.nav.level-1 < len(r.nav.titles) {
r.title.Text = r.nav.titles[r.nav.level-1]
} else {
r.title.Text = r.nav.Title
}
r.object.Refresh()
}