Tighten author logo branding layout

This commit is contained in:
Stu Leak 2026-01-07 01:49:17 -05:00
parent 91c6caeaa0
commit 9fdd8b5daf

View File

@ -1029,15 +1029,22 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
logoEnableCheck := widget.NewCheck("Embed Logo", nil) logoEnableCheck := widget.NewCheck("Embed Logo", nil)
logoEnableCheck.SetChecked(state.authorMenuLogoEnabled) logoEnableCheck.SetChecked(state.authorMenuLogoEnabled)
logoLabel := widget.NewLabel(state.authorMenuLogoPath) logoLabel := widget.NewLabel("")
logoLabel.Wrapping = fyne.TextWrapWord logoLabel.Wrapping = fyne.TextWrapWord
logoPreview := canvas.NewImageFromFile("") logoPreview := canvas.NewImageFromFile("")
logoPreview.FillMode = canvas.ImageFillContain logoPreview.FillMode = canvas.ImageFillContain
logoPreview.SetMinSize(fyne.NewSize(220, 120)) logoPreview.SetMinSize(fyne.NewSize(96, 96))
logoPreviewLabel := widget.NewLabel("No logo selected") logoPreviewLabel := widget.NewLabel("No logo selected")
logoPreviewLabel.Wrapping = fyne.TextWrapWord logoPreviewLabel.Wrapping = fyne.TextWrapWord
logoPreviewSize := widget.NewLabel("") logoPreviewSize := widget.NewLabel("")
logoPreviewSize.Wrapping = fyne.TextWrapWord logoPreviewSize.Wrapping = fyne.TextWrapWord
logoPreviewBorder := canvas.NewRectangle(color.NRGBA{R: 80, G: 86, B: 100, A: 120})
logoPreviewBorder.SetMinSize(fyne.NewSize(120, 96))
logoPreviewBox := container.NewMax(
logoPreviewBorder,
container.NewPadded(logoPreview),
)
var updateBrandingTitle func()
menuPreviewSize := func() (int, int) { menuPreviewSize := func() (int, int) {
width := 720 width := 720
@ -1049,10 +1056,18 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
return width, height return width, height
} }
logoDisplayName := func() string {
if strings.TrimSpace(state.authorMenuLogoPath) == "" {
return "VT_Logo.png (default)"
}
return filepath.Base(state.authorMenuLogoPath)
}
updateLogoPreview := func() { updateLogoPreview := func() {
logoLabel.SetText(logoDisplayName())
if !state.authorMenuLogoEnabled { if !state.authorMenuLogoEnabled {
logoPreview.Hide() logoPreviewBox.Hide()
logoPreviewLabel.SetText("Logo preview disabled") logoPreviewLabel.SetText("Logo disabled")
logoPreviewSize.SetText("") logoPreviewSize.SetText("")
return return
} }
@ -1063,13 +1078,13 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
} }
if _, err := os.Stat(path); err != nil { if _, err := os.Stat(path); err != nil {
logoPreview.Hide() logoPreviewBox.Hide()
logoPreviewLabel.SetText("Logo file not found") logoPreviewLabel.SetText("Logo file not found")
logoPreviewSize.SetText("") logoPreviewSize.SetText("")
return return
} }
logoPreview.Show() logoPreviewBox.Show()
logoPreviewLabel.SetText(filepath.Base(path)) logoPreviewLabel.SetText(filepath.Base(path))
logoPreview.File = path logoPreview.File = path
logoPreview.Refresh() logoPreview.Refresh()
@ -1110,13 +1125,19 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
} }
defer reader.Close() defer reader.Close()
state.authorMenuLogoPath = reader.URI().Path() state.authorMenuLogoPath = reader.URI().Path()
logoLabel.SetText(state.authorMenuLogoPath) logoLabel.SetText(logoDisplayName())
updateLogoPreview() updateLogoPreview()
updateBrandingTitle()
state.updateAuthorSummary() state.updateAuthorSummary()
state.persistAuthorConfig() state.persistAuthorConfig()
}, state.window) }, state.window)
}) })
logoPickButton.Importance = widget.MediumImportance logoPickButton.Importance = widget.MediumImportance
logoClearButton := widget.NewButton("Clear", func() {
state.authorMenuLogoPath = ""
logoLabel.SetText(logoDisplayName())
logoEnableCheck.SetChecked(false)
})
logoPositionSelect := widget.NewSelect([]string{ logoPositionSelect := widget.NewSelect([]string{
"Top Left", "Top Left",
@ -1126,6 +1147,7 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
"Center", "Center",
}, func(value string) { }, func(value string) {
state.authorMenuLogoPosition = value state.authorMenuLogoPosition = value
updateBrandingTitle()
state.persistAuthorConfig() state.persistAuthorConfig()
}) })
if state.authorMenuLogoPosition == "" { if state.authorMenuLogoPosition == "" {
@ -1157,6 +1179,7 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
if scale, ok := scaleValueByLabel[value]; ok { if scale, ok := scaleValueByLabel[value]; ok {
state.authorMenuLogoScale = scale state.authorMenuLogoScale = scale
updateLogoPreview() updateLogoPreview()
updateBrandingTitle()
state.persistAuthorConfig() state.persistAuthorConfig()
} }
}) })
@ -1170,15 +1193,44 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
if state.authorMenuLogoMargin == 0 { if state.authorMenuLogoMargin == 0 {
state.authorMenuLogoMargin = 24 state.authorMenuLogoMargin = 24
} }
marginLabel := widget.NewLabel(fmt.Sprintf("Logo Margin: %dpx", state.authorMenuLogoMargin)) marginEntry := widget.NewEntry()
marginSlider := widget.NewSlider(0, 60) marginEntry.SetText(strconv.Itoa(state.authorMenuLogoMargin))
marginSlider.Step = 2 updatingMargin := false
marginSlider.Value = float64(state.authorMenuLogoMargin) updateMargin := func(value int, updateEntry bool) {
marginSlider.OnChanged = func(v float64) { if value < 0 {
state.authorMenuLogoMargin = int(math.Round(v)) value = 0
marginLabel.SetText(fmt.Sprintf("Logo Margin: %dpx", state.authorMenuLogoMargin)) }
if value > 60 {
value = 60
}
state.authorMenuLogoMargin = value
if updateEntry {
updatingMargin = true
marginEntry.SetText(strconv.Itoa(value))
updatingMargin = false
}
state.persistAuthorConfig() state.persistAuthorConfig()
} }
marginEntry.OnChanged = func(value string) {
if updatingMargin {
return
}
if strings.TrimSpace(value) == "" {
return
}
if v, err := strconv.Atoi(value); err == nil {
if v == state.authorMenuLogoMargin {
return
}
updateMargin(v, true)
}
}
marginMinus := widget.NewButton("-", func() {
updateMargin(state.authorMenuLogoMargin-2, true)
})
marginPlus := widget.NewButton("+", func() {
updateMargin(state.authorMenuLogoMargin+2, true)
})
safeAreaNote := widget.NewLabel("Logos are constrained to DVD safe areas.") safeAreaNote := widget.NewLabel("Logos are constrained to DVD safe areas.")
safeAreaNote.TextStyle = fyne.TextStyle{Italic: true} safeAreaNote.TextStyle = fyne.TextStyle{Italic: true}
@ -1224,12 +1276,37 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
info.Wrapping = fyne.TextWrapWord info.Wrapping = fyne.TextWrapWord
logoPreviewGroup := container.NewVBox( logoPreviewGroup := container.NewVBox(
widget.NewLabel("Logo Preview:"), widget.NewLabel("Preview:"),
logoPreviewLabel, logoPreviewLabel,
logoPreview, logoPreviewBox,
logoPreviewSize, logoPreviewSize,
) )
logoFileRow := container.NewHBox(
logoLabel,
layout.NewSpacer(),
logoPickButton,
logoClearButton,
)
logoPositionRow := container.NewHBox(
widget.NewLabel("Position:"),
layout.NewSpacer(),
logoPositionSelect,
)
logoScaleRow := container.NewHBox(
widget.NewLabel("Scale:"),
layout.NewSpacer(),
logoScaleSelect,
)
logoMarginRow := container.NewHBox(
widget.NewLabel("Margin:"),
marginMinus,
marginEntry,
marginPlus,
widget.NewLabel("px"),
)
menuCore := buildMenuBox("Menu Core", container.NewVBox( menuCore := buildMenuBox("Menu Core", container.NewVBox(
createMenuCheck, createMenuCheck,
menuDisabledNote, menuDisabledNote,
@ -1243,20 +1320,30 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
menuStructureSelect, menuStructureSelect,
)) ))
branding := buildMenuBox("Branding", container.NewVBox( brandingContent := container.NewGridWithColumns(2,
logoEnableCheck, container.NewVBox(
widget.NewLabel("Logo Path:"), logoEnableCheck,
logoLabel, widget.NewLabel("Logo File:"),
logoPickButton, logoFileRow,
logoPositionRow,
logoScaleRow,
logoMarginRow,
safeAreaNote,
),
logoPreviewGroup, logoPreviewGroup,
widget.NewLabel("Logo Position:"), )
logoPositionSelect, brandingItem := widget.NewAccordionItem("Branding (Logo Overlay)", brandingContent)
widget.NewLabel("Logo Scale:"), brandingItem.Open = false
logoScaleSelect, brandingAccordion := widget.NewAccordion(brandingItem)
marginLabel, branding := container.NewMax(
marginSlider, canvas.NewRectangle(navyBlue),
safeAreaNote, container.NewPadded(brandingAccordion),
)) )
if bg, ok := branding.Objects[0].(*canvas.Rectangle); ok {
bg.CornerRadius = 10
bg.StrokeColor = boxAccent
bg.StrokeWidth = 1
}
navigation := buildMenuBox("Navigation", container.NewVBox( navigation := buildMenuBox("Navigation", container.NewVBox(
extrasMenuCheck, extrasMenuCheck,
@ -1294,9 +1381,12 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
menuStructureSelect, menuStructureSelect,
logoEnableCheck, logoEnableCheck,
logoPickButton, logoPickButton,
logoClearButton,
logoPositionSelect, logoPositionSelect,
logoScaleSelect, logoScaleSelect,
marginSlider, marginEntry,
marginMinus,
marginPlus,
extrasMenuCheck, extrasMenuCheck,
thumbSourceSelect, thumbSourceSelect,
) )
@ -1304,21 +1394,41 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
logoControlsEnabled := enabled && state.authorMenuLogoEnabled logoControlsEnabled := enabled && state.authorMenuLogoEnabled
setEnabled(logoControlsEnabled, setEnabled(logoControlsEnabled,
logoPickButton, logoPickButton,
logoClearButton,
logoPositionSelect, logoPositionSelect,
logoScaleSelect, logoScaleSelect,
marginSlider, marginEntry,
marginMinus,
marginPlus,
) )
} }
updateBrandingTitle = func() {
if !state.authorMenuLogoEnabled {
brandingItem.Title = "Branding: Disabled"
brandingAccordion.Refresh()
return
}
scaleText := scaleLabelByValue[state.authorMenuLogoScale]
if scaleText == "" {
scaleText = "100%"
}
name := logoDisplayName()
brandingItem.Title = fmt.Sprintf("Branding: %s (%s, %s)", name, state.authorMenuLogoPosition, scaleText)
brandingAccordion.Refresh()
}
logoEnableCheck.OnChanged = func(checked bool) { logoEnableCheck.OnChanged = func(checked bool) {
state.authorMenuLogoEnabled = checked state.authorMenuLogoEnabled = checked
updateLogoPreview() updateLogoPreview()
updateBrandingTitle()
updateMenuControls(state.authorCreateMenu) updateMenuControls(state.authorCreateMenu)
state.updateAuthorSummary() state.updateAuthorSummary()
state.persistAuthorConfig() state.persistAuthorConfig()
} }
updateLogoPreview() updateLogoPreview()
updateBrandingTitle()
updateMenuControls(state.authorCreateMenu) updateMenuControls(state.authorCreateMenu)
scroll := container.NewVScroll(container.NewPadded(controls)) scroll := container.NewVScroll(container.NewPadded(controls))