Fix convert layout stacking and cgo build
This commit is contained in:
parent
a56113b8cc
commit
97781b625f
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,4 +1,3 @@
|
||||||
videotools.log
|
videotools.log
|
||||||
.gocache/
|
.gocache/
|
||||||
.gomodcache/
|
.gomodcache/
|
||||||
VideoTools
|
|
||||||
|
|
|
||||||
BIN
VideoTools
Executable file
BIN
VideoTools
Executable file
Binary file not shown.
|
|
@ -424,7 +424,8 @@ func (r *conversionStatsRenderer) Layout(size fyne.Size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *conversionStatsRenderer) MinSize() fyne.Size {
|
func (r *conversionStatsRenderer) MinSize() fyne.Size {
|
||||||
return fyne.NewSize(400, 32)
|
// Only constrain height, allow width to flex
|
||||||
|
return fyne.NewSize(0, 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *conversionStatsRenderer) Refresh() {
|
func (r *conversionStatsRenderer) Refresh() {
|
||||||
|
|
|
||||||
102
main.go
102
main.go
|
|
@ -1159,8 +1159,10 @@ func runGUI() {
|
||||||
} else {
|
} else {
|
||||||
logging.Debug(logging.CatUI, "app icon not found; continuing without custom icon")
|
logging.Debug(logging.CatUI, "app icon not found; continuing without custom icon")
|
||||||
}
|
}
|
||||||
w.Resize(fyne.NewSize(1120, 640))
|
// Use a generous default window size that fits typical desktops without overflowing.
|
||||||
logging.Debug(logging.CatUI, "window initialized at 1120x640")
|
w.Resize(fyne.NewSize(1280, 800))
|
||||||
|
w.SetFixedSize(false) // Allow manual resizing
|
||||||
|
logging.Debug(logging.CatUI, "window initialized with manual resizing enabled")
|
||||||
|
|
||||||
state := &appState{
|
state := &appState{
|
||||||
window: w,
|
window: w,
|
||||||
|
|
@ -1420,8 +1422,9 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
videoPanel := buildVideoPane(state, fyne.NewSize(360, 230), src, updateCover)
|
// Make panel sizes responsive with modest minimums to avoid forcing the window beyond the screen
|
||||||
metaPanel, metaCoverUpdate := buildMetadataPanel(state, src, fyne.NewSize(360, 150))
|
videoPanel := buildVideoPane(state, fyne.NewSize(460, 260), src, updateCover)
|
||||||
|
metaPanel, metaCoverUpdate := buildMetadataPanel(state, src, fyne.NewSize(0, 200))
|
||||||
updateMetaCover = metaCoverUpdate
|
updateMetaCover = metaCoverUpdate
|
||||||
|
|
||||||
var formatLabels []string
|
var formatLabels []string
|
||||||
|
|
@ -1537,7 +1540,8 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
|
|
||||||
// Settings management for batch operations
|
// Settings management for batch operations
|
||||||
settingsInfoLabel := widget.NewLabel("Settings persist across videos. Change them anytime to affect all subsequent videos.")
|
settingsInfoLabel := widget.NewLabel("Settings persist across videos. Change them anytime to affect all subsequent videos.")
|
||||||
settingsInfoLabel.Wrapping = fyne.TextWrapWord
|
// Don't wrap - let text scroll or truncate if needed
|
||||||
|
settingsInfoLabel.Alignment = fyne.TextAlignCenter
|
||||||
|
|
||||||
resetSettingsBtn := widget.NewButton("Reset to Defaults", func() {
|
resetSettingsBtn := widget.NewButton("Reset to Defaults", func() {
|
||||||
// Reset to default settings
|
// Reset to default settings
|
||||||
|
|
@ -1569,10 +1573,33 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
})
|
})
|
||||||
resetSettingsBtn.Importance = widget.LowImportance
|
resetSettingsBtn.Importance = widget.LowImportance
|
||||||
|
|
||||||
settingsBox := container.NewVBox(
|
// Create collapsible batch settings section
|
||||||
widget.NewLabelWithStyle("═══ BATCH SETTINGS ═══", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
|
settingsContent := container.NewVBox(
|
||||||
settingsInfoLabel,
|
settingsInfoLabel,
|
||||||
resetSettingsBtn,
|
resetSettingsBtn,
|
||||||
|
)
|
||||||
|
settingsContent.Hide() // Hidden by default
|
||||||
|
|
||||||
|
// Use a pointer to track visibility state
|
||||||
|
settingsVisible := false
|
||||||
|
|
||||||
|
var toggleSettingsBtn *widget.Button
|
||||||
|
toggleSettingsBtn = widget.NewButton("Show Batch Settings", func() {
|
||||||
|
if settingsVisible {
|
||||||
|
settingsContent.Hide()
|
||||||
|
toggleSettingsBtn.SetText("Show Batch Settings")
|
||||||
|
settingsVisible = false
|
||||||
|
} else {
|
||||||
|
settingsContent.Show()
|
||||||
|
toggleSettingsBtn.SetText("Hide Batch Settings")
|
||||||
|
settingsVisible = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
toggleSettingsBtn.Importance = widget.LowImportance
|
||||||
|
|
||||||
|
settingsBox := container.NewVBox(
|
||||||
|
toggleSettingsBtn,
|
||||||
|
settingsContent,
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1780,9 +1807,13 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
simpleOptions,
|
simpleOptions,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Avoid nested scrolls capturing wheel events; let the outer page scroll handle overflow.
|
||||||
|
simpleScrollBox := simpleWithSettings
|
||||||
|
advancedScrollBox := advancedOptions
|
||||||
|
|
||||||
tabs := container.NewAppTabs(
|
tabs := container.NewAppTabs(
|
||||||
container.NewTabItem("Simple", container.NewVScroll(simpleWithSettings)),
|
container.NewTabItem("Simple", simpleScrollBox),
|
||||||
container.NewTabItem("Advanced", container.NewVScroll(advancedOptions)),
|
container.NewTabItem("Advanced", advancedScrollBox),
|
||||||
)
|
)
|
||||||
tabs.SetTabLocation(container.TabLocationTop)
|
tabs.SetTabLocation(container.TabLocationTop)
|
||||||
|
|
||||||
|
|
@ -1831,15 +1862,16 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
}
|
}
|
||||||
snippetHint := widget.NewLabel("Creates a 20s clip centred on the timeline midpoint.")
|
snippetHint := widget.NewLabel("Creates a 20s clip centred on the timeline midpoint.")
|
||||||
snippetRow := container.NewHBox(snippetBtn, layout.NewSpacer(), snippetHint)
|
snippetRow := container.NewHBox(snippetBtn, layout.NewSpacer(), snippetHint)
|
||||||
// Use VSplit to make panels expand vertically and fill available space
|
|
||||||
leftColumn := container.NewVSplit(videoPanel, metaPanel)
|
// Stack video and metadata directly so metadata sits immediately under the player.
|
||||||
leftColumn.Offset = 0.65 // Video pane gets 65% of space, metadata gets 35%
|
leftColumn := container.NewVBox(videoPanel, metaPanel)
|
||||||
|
|
||||||
|
// Split: left side (video + metadata VSplit) takes 55% | right side (options) takes 45%
|
||||||
mainSplit := container.NewHSplit(leftColumn, optionsPanel)
|
mainSplit := container.NewHSplit(leftColumn, optionsPanel)
|
||||||
mainSplit.Offset = 0.45 // Give the options panel extra horizontal room
|
mainSplit.Offset = 0.55 // Video/metadata column gets 55%, options gets 45%
|
||||||
mainArea := container.NewPadded(container.NewVBox(
|
|
||||||
mainSplit,
|
// Core content now just the split; ancillary controls stack in bottomSection.
|
||||||
snippetRow,
|
mainContent := container.NewMax(mainSplit)
|
||||||
))
|
|
||||||
|
|
||||||
resetBtn := widget.NewButton("Reset", func() {
|
resetBtn := widget.NewButton("Reset", func() {
|
||||||
tabs.SelectIndex(0) // Select Simple tab
|
tabs.SelectIndex(0) // Select Simple tab
|
||||||
|
|
@ -1922,12 +1954,12 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
addQueueBtn.Enable()
|
addQueueBtn.Enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
actionInner := container.NewHBox(resetBtn, activity, statusLabel, layout.NewSpacer(), cancelBtn, addQueueBtn, convertBtn)
|
leftControls := container.NewHBox(resetBtn)
|
||||||
|
centerStatus := container.NewHBox(activity, statusLabel)
|
||||||
|
rightControls := container.NewHBox(cancelBtn, addQueueBtn, convertBtn)
|
||||||
|
actionInner := container.NewBorder(nil, nil, leftControls, rightControls, centerStatus)
|
||||||
actionBar := ui.TintedBar(convertColor, actionInner)
|
actionBar := ui.TintedBar(convertColor, actionInner)
|
||||||
|
|
||||||
// Wrap mainArea in a scroll container to prevent content from forcing window resize
|
|
||||||
scrollableMain := container.NewScroll(mainArea)
|
|
||||||
|
|
||||||
// Start a UI refresh ticker to update widgets from state while conversion is active
|
// Start a UI refresh ticker to update widgets from state while conversion is active
|
||||||
// This ensures progress updates even when navigating between modules
|
// This ensures progress updates even when navigating between modules
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -1993,20 +2025,12 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
// Update stats bar
|
// Update stats bar
|
||||||
state.updateStatsBar()
|
state.updateStatsBar()
|
||||||
|
|
||||||
// Add stats bar above the action bar at the bottom
|
// Stack status + snippet + actions tightly to avoid dead air, outside the scroll area.
|
||||||
bottomSection := container.NewVBox(
|
bottomSection := container.NewVBox(state.statsBar, snippetRow, widget.NewSeparator(), actionBar)
|
||||||
state.statsBar,
|
|
||||||
widget.NewSeparator(),
|
|
||||||
actionBar,
|
|
||||||
)
|
|
||||||
|
|
||||||
return container.NewBorder(
|
scrollableMain := container.NewVScroll(mainContent)
|
||||||
backBar,
|
|
||||||
bottomSection,
|
return container.NewBorder(backBar, bottomSection, nil, nil, container.NewMax(scrollableMain))
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
scrollableMain,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLabeledPanel(title, body string, min fyne.Size) *fyne.Container {
|
func makeLabeledPanel(title, body string, min fyne.Size) *fyne.Container {
|
||||||
|
|
@ -2249,11 +2273,13 @@ func buildVideoPane(state *appState, min fyne.Size, src *videoSource, onCover fu
|
||||||
img = canvas.NewImageFromResource(nil)
|
img = canvas.NewImageFromResource(nil)
|
||||||
}
|
}
|
||||||
img.FillMode = canvas.ImageFillContain
|
img.FillMode = canvas.ImageFillContain
|
||||||
img.SetMinSize(fyne.NewSize(targetWidth-28, targetHeight-40))
|
// Let the image grow with the available stage size
|
||||||
|
img.SetMinSize(fyne.NewSize(targetWidth, targetHeight))
|
||||||
stage := canvas.NewRectangle(utils.MustHex("#0F1529"))
|
stage := canvas.NewRectangle(utils.MustHex("#0F1529"))
|
||||||
stage.CornerRadius = 6
|
stage.CornerRadius = 6
|
||||||
stage.SetMinSize(fyne.NewSize(targetWidth-12, targetHeight-12))
|
stage.SetMinSize(fyne.NewSize(targetWidth, targetHeight))
|
||||||
videoStage := container.NewMax(stage, container.NewPadded(container.NewCenter(img)))
|
// Overlay the image directly so it fills the stage while preserving aspect.
|
||||||
|
videoStage := container.NewMax(stage, img)
|
||||||
|
|
||||||
coverBtn := utils.MakeIconButton("⌾", "Set current frame as cover art", func() {
|
coverBtn := utils.MakeIconButton("⌾", "Set current frame as cover art", func() {
|
||||||
path, err := state.captureCoverFromCurrent()
|
path, err := state.captureCoverFromCurrent()
|
||||||
|
|
@ -2454,7 +2480,7 @@ func buildVideoPane(state *appState, min fyne.Size, src *videoSource, onCover fu
|
||||||
stack := container.NewVBox(
|
stack := container.NewVBox(
|
||||||
container.NewPadded(videoWithOverlay),
|
container.NewPadded(videoWithOverlay),
|
||||||
)
|
)
|
||||||
return container.NewMax(outer, container.NewCenter(container.NewPadded(stack)))
|
return container.NewMax(outer, container.NewPadded(stack))
|
||||||
}
|
}
|
||||||
|
|
||||||
type playSession struct {
|
type playSession struct {
|
||||||
|
|
|
||||||
BIN
screenshot.png
Normal file
BIN
screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1016 KiB |
|
|
@ -38,7 +38,9 @@ echo "✓ Dependencies verified"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "🔨 Building VideoTools..."
|
echo "🔨 Building VideoTools..."
|
||||||
if CGO_ENABLED=0 go build -o "$BUILD_OUTPUT" .; then
|
# Fyne needs cgo for GLFW/OpenGL bindings; build with CGO enabled.
|
||||||
|
export CGO_ENABLED=1
|
||||||
|
if go build -o "$BUILD_OUTPUT" .; then
|
||||||
echo "✓ Build successful!"
|
echo "✓ Build successful!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "════════════════════════════════════════════════════════════════"
|
echo "════════════════════════════════════════════════════════════════"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user