Leonid Nikitin 394824ce88
Add layout system and file selection logic
Introduce a new layout system for managing main window content and tabs. Integrate file selection and drag-and-drop functionality for adding files to the conversion list, with automatic tab switching to "Added Files". Refactor existing components to support these features.
2025-06-07 23:44:47 +05:00

173 lines
4.1 KiB
Go

package view
import (
"errors"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/gui/window"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/utils"
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
"image/color"
"os"
"path/filepath"
)
func Convertor(window window.WindowContract, addFileForConversion func(file ffmpeg.File)) fyne.CanvasObject {
form := newFormConvertor(window, addFileForConversion)
converterVideoFilesTitle := lang.L("converterVideoFilesTitle")
return widget.NewCard(converterVideoFilesTitle, "", container.NewVScroll(form.getForm()))
}
type formConvertor struct {
form *widget.Form
items []*widget.FormItem
window window.WindowContract
addFileForConversion func(file ffmpeg.File)
}
func newFormConvertor(window window.WindowContract, addFileForConversion func(file ffmpeg.File)) *formConvertor {
f := widget.NewForm()
f.SubmitText = lang.L("converterVideoFilesSubmitTitle")
formConvertor := &formConvertor{
form: f,
window: window,
addFileForConversion: addFileForConversion,
}
fileForConversion := formConvertor.newFileForConversion()
items := []*widget.FormItem{
{
Text: lang.L("fileForConversionTitle"),
Widget: fileForConversion.button,
},
{
Widget: container.NewHScroll(fileForConversion.message),
},
}
formConvertor.form.Items = items
formConvertor.items = items
return formConvertor
}
func (f *formConvertor) getForm() *widget.Form {
return f.form
}
type fileForConversion struct {
button *widget.Button
message *canvas.Text
file *kernel.File
changeCallbacks map[int]func(err error)
}
func (f *formConvertor) newFileForConversion() *fileForConversion {
message := canvas.NewText("", color.RGBA{R: 255, G: 0, B: 0, A: 255})
fileForConversion := &fileForConversion{
message: message,
changeCallbacks: map[int]func(err error){},
}
buttonTitle := lang.L("choose") + "\n" +
lang.L("or") + "\n" +
lang.L("dragAndDropFiles")
var locationURI fyne.ListableURI
fileForConversion.button = widget.NewButton(buttonTitle, func() {
f.window.NewFileOpen(func(r fyne.URIReadCloser, err error) {
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
if err != nil {
fyne.Do(func() {
fileForConversion.message.Text = err.Error()
fileForConversion.message.Refresh()
})
fileForConversion.eventSelectFile(err)
return
}
if r == nil {
return
}
f.addFileForConversion(ffmpeg.File{
Path: r.URI().Path(),
Name: r.URI().Name(),
Ext: r.URI().Extension(),
})
fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(r.URI().Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}, locationURI)
})
f.window.SetOnDropped(func(position fyne.Position, uris []fyne.URI) {
if len(uris) == 0 {
return
}
isError := false
for _, uri := range uris {
info, err := os.Stat(uri.Path())
if err != nil {
isError = true
continue
}
if info.IsDir() {
isError = true
continue
}
f.addFileForConversion(ffmpeg.File{
Path: uri.Path(),
Name: uri.Name(),
Ext: uri.Extension(),
})
fileForConversion.eventSelectFile(nil)
listableURI := storage.NewFileURI(filepath.Dir(uri.Path()))
locationURI, _ = storage.ListerForURI(listableURI)
}
if isError {
fileForConversion.message.Text = lang.L("errorDragAndDropFile")
utils.SetStringErrorStyle(fileForConversion.message)
fileForConversion.eventSelectFile(errors.New(fileForConversion.message.Text))
} else {
fyne.Do(func() {
fileForConversion.message.Text = ""
fileForConversion.message.Refresh()
})
}
})
return fileForConversion
}
func (c *fileForConversion) addChangeCallback(callback func(err error)) {
c.changeCallbacks[len(c.changeCallbacks)] = callback
}
func (c *fileForConversion) eventSelectFile(err error) {
for _, changeCallback := range c.changeCallbacks {
changeCallback(err)
}
}