package window import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/lang" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/application/convertor" "git.kor-elf.net/kor-elf/gui-for-ffmpeg/internal/ffmpeg" "image/color" "strconv" "strings" ) type QueueLayoutContract interface { GetItemsContainer() *fyne.Container GetQueueStatistics() QueueStatisticsAllContract AddQueue(key int, queue *convertor.Queue) ChangeQueue(key int, queue *convertor.Queue) RemoveQueue(key int, status convertor.StatusContract) } type queueLayout struct { itemsContainer *fyne.Container queueAllStatistics QueueStatisticsAllContract items map[int]queueLayoutItem ffmpegService ffmpeg.UtilitiesContract } func NewQueueLayout(ffmpegService ffmpeg.UtilitiesContract) QueueLayoutContract { items := map[int]queueLayoutItem{} return &queueLayout{ itemsContainer: container.NewVBox(), queueAllStatistics: newQueueAllStatistics(&items), items: items, ffmpegService: ffmpegService, } } func (l *queueLayout) GetItemsContainer() *fyne.Container { return l.itemsContainer } func (l *queueLayout) GetQueueStatistics() QueueStatisticsAllContract { return l.queueAllStatistics } func (l *queueLayout) AddQueue(queueID int, queue *convertor.Queue) { statusMessage := canvas.NewText(l.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary)) messageError := canvas.NewText("", theme.Color(theme.ColorNameError)) buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() { }) buttonPlay.Hide() blockMessageError := container.NewHScroll(messageError) blockMessageError.Hide() content := container.NewVBox( container.NewHScroll(widget.NewLabel(queue.Setting.FileInput.Name)), container.NewHBox( buttonPlay, statusMessage, ), blockMessageError, container.NewPadded(), canvas.NewLine(theme.Color(theme.ColorNameFocus)), container.NewPadded(), ) l.addQueueStatistics() if l.GetQueueStatistics().IsChecked(queue.Status) == false { content.Hide() } l.items[queueID] = queueLayoutItem{ CanvasObject: content, StatusMessage: statusMessage, BlockMessageError: blockMessageError, MessageError: messageError, buttonPlay: buttonPlay, status: queue.Status, } l.itemsContainer.Add(content) } func (l *queueLayout) ChangeQueue(queueID int, queue *convertor.Queue) { if item, ok := l.items[queueID]; ok { statusColor := l.getStatusColor(queue.Status) fyne.Do(func() { item.StatusMessage.Text = l.getStatusTitle(queue.Status) item.StatusMessage.Color = statusColor item.StatusMessage.Refresh() }) if queue.Error != nil { fyne.Do(func() { item.MessageError.Text = queue.Error.Error() item.MessageError.Color = statusColor item.BlockMessageError.Show() item.MessageError.Refresh() }) } if queue.Status == convertor.StatusType(convertor.Completed) { item.buttonPlay.Show() item.buttonPlay.OnTapped = func() { item.buttonPlay.Disable() go func() { ffplay, err := l.ffmpegService.GetFFplay() if err == nil { _ = ffplay.Play(&queue.Setting.FileOut) } fyne.Do(func() { item.buttonPlay.Enable() }) }() } } if l.GetQueueStatistics().IsChecked(queue.Status) == false && item.CanvasObject.Visible() == true { item.CanvasObject.Hide() } else if item.CanvasObject.Visible() == false { item.CanvasObject.Show() } l.changeQueueStatistics(queue.Status) } } func (l *queueLayout) RemoveQueue(queueID int, status convertor.StatusContract) { if item, ok := l.items[queueID]; ok { l.itemsContainer.Remove(item.CanvasObject) l.removeQueueStatistics(status) l.items[queueID] = queueLayoutItem{} } } func (l *queueLayout) addQueueStatistics() { l.GetQueueStatistics().GetWaiting().Add() l.GetQueueStatistics().GetTotal().Add() } func (l *queueLayout) changeQueueStatistics(status convertor.StatusContract) { if status == convertor.StatusType(convertor.InProgress) { l.GetQueueStatistics().GetWaiting().Remove() l.GetQueueStatistics().GetInProgress().Add() return } if status == convertor.StatusType(convertor.Completed) { l.GetQueueStatistics().GetInProgress().Remove() l.GetQueueStatistics().GetCompleted().Add() return } if status == convertor.StatusType(convertor.Error) { l.GetQueueStatistics().GetInProgress().Remove() l.GetQueueStatistics().GetError().Add() return } } func (l *queueLayout) removeQueueStatistics(status convertor.StatusContract) { l.GetQueueStatistics().GetTotal().Remove() if status == convertor.StatusType(convertor.Completed) { l.GetQueueStatistics().GetCompleted().Remove() return } if status == convertor.StatusType(convertor.Error) { l.GetQueueStatistics().GetError().Remove() return } if status == convertor.StatusType(convertor.InProgress) { l.GetQueueStatistics().GetInProgress().Remove() return } if status == convertor.StatusType(convertor.Waiting) { l.GetQueueStatistics().GetWaiting().Remove() return } } func (l *queueLayout) getStatusTitle(status convertor.StatusContract) string { return lang.L(status.Name() + "Queue") } func (l *queueLayout) getStatusColor(status convertor.StatusContract) color.Color { if status == convertor.StatusType(convertor.Error) { return theme.Color(theme.ColorNameError) } if status == convertor.StatusType(convertor.Completed) { return color.RGBA{R: 49, G: 127, B: 114, A: 255} } return theme.Color(theme.ColorNamePrimary) } type QueueStatisticsAllContract interface { GetWaiting() QueueStatisticsContract GetInProgress() QueueStatisticsContract GetCompleted() QueueStatisticsContract GetError() QueueStatisticsContract GetTotal() QueueStatisticsContract IsChecked(status convertor.StatusContract) bool } type queueAllStatistics struct { waiting QueueStatisticsContract inProgress QueueStatisticsContract completed QueueStatisticsContract error QueueStatisticsContract total QueueStatisticsContract } func newQueueAllStatistics(queueItems *map[int]queueLayoutItem) QueueStatisticsAllContract { checkboxWaiting := newQueueStatistics() checkboxInProgress := newQueueStatistics() checkboxCompleted := newQueueStatistics() checkboxError := newQueueStatistics() CheckboxTotal := newQueueStatistics() queueAllStatistics := &queueAllStatistics{ waiting: checkboxWaiting, inProgress: checkboxInProgress, completed: checkboxCompleted, error: checkboxError, total: CheckboxTotal, } CheckboxTotal.GetCheckbox().OnChanged = func(b bool) { if b == true { queueAllStatistics.allCheckboxChecked() } else { queueAllStatistics.allUnCheckboxChecked() } queueAllStatistics.redrawingQueueItems(queueItems) } checkboxWaiting.GetCheckbox().OnChanged = func(b bool) { if b == true { queueAllStatistics.checkboxChecked() } else { queueAllStatistics.unCheckboxChecked() } queueAllStatistics.redrawingQueueItems(queueItems) } checkboxInProgress.GetCheckbox().OnChanged = func(b bool) { if b == true { queueAllStatistics.checkboxChecked() } else { queueAllStatistics.unCheckboxChecked() } queueAllStatistics.redrawingQueueItems(queueItems) } checkboxCompleted.GetCheckbox().OnChanged = func(b bool) { if b == true { queueAllStatistics.checkboxChecked() } else { queueAllStatistics.unCheckboxChecked() } queueAllStatistics.redrawingQueueItems(queueItems) } checkboxError.GetCheckbox().OnChanged = func(b bool) { if b == true { queueAllStatistics.checkboxChecked() } else { queueAllStatistics.unCheckboxChecked() } queueAllStatistics.redrawingQueueItems(queueItems) } return queueAllStatistics } func (s *queueAllStatistics) GetWaiting() QueueStatisticsContract { return s.waiting } func (s *queueAllStatistics) GetInProgress() QueueStatisticsContract { return s.inProgress } func (s *queueAllStatistics) GetCompleted() QueueStatisticsContract { return s.completed } func (s *queueAllStatistics) GetError() QueueStatisticsContract { return s.error } func (s *queueAllStatistics) GetTotal() QueueStatisticsContract { return s.total } func (s *queueAllStatistics) IsChecked(status convertor.StatusContract) bool { if status == convertor.StatusType(convertor.InProgress) { return s.inProgress.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Completed) { return s.completed.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Error) { return s.error.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Waiting) { return s.waiting.GetCheckbox().Checked } return true } func (s *queueAllStatistics) redrawingQueueItems(queueItems *map[int]queueLayoutItem) { for _, item := range *queueItems { if s.isChecked(item.status) == true && item.CanvasObject.Visible() == false { item.CanvasObject.Show() continue } if s.isChecked(item.status) == false && item.CanvasObject.Visible() == true { item.CanvasObject.Hide() } } } func (s *queueAllStatistics) isChecked(status convertor.StatusContract) bool { if status == convertor.StatusType(convertor.InProgress) { return s.inProgress.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Completed) { return s.completed.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Error) { return s.error.GetCheckbox().Checked } if status == convertor.StatusType(convertor.Waiting) { return s.waiting.GetCheckbox().Checked } return true } func (s *queueAllStatistics) checkboxChecked() { if s.total.GetCheckbox().Checked == true { return } if s.waiting.GetCheckbox().Checked == false { return } if s.inProgress.GetCheckbox().Checked == false { return } if s.completed.GetCheckbox().Checked == false { return } if s.error.GetCheckbox().Checked == false { return } s.total.GetCheckbox().Checked = true s.total.GetCheckbox().Refresh() } func (s *queueAllStatistics) unCheckboxChecked() { if s.total.GetCheckbox().Checked == false { return } s.total.GetCheckbox().Checked = false s.total.GetCheckbox().Refresh() } func (s *queueAllStatistics) allCheckboxChecked() { s.waiting.GetCheckbox().Checked = true s.waiting.GetCheckbox().Refresh() s.inProgress.GetCheckbox().Checked = true s.inProgress.GetCheckbox().Refresh() s.completed.GetCheckbox().Checked = true s.completed.GetCheckbox().Refresh() s.error.GetCheckbox().Checked = true s.error.GetCheckbox().Refresh() } func (s *queueAllStatistics) allUnCheckboxChecked() { s.waiting.GetCheckbox().Checked = false s.waiting.GetCheckbox().Refresh() s.inProgress.GetCheckbox().Checked = false s.inProgress.GetCheckbox().Refresh() s.completed.GetCheckbox().Checked = false s.completed.GetCheckbox().Refresh() s.error.GetCheckbox().Checked = false s.error.GetCheckbox().Refresh() } type QueueStatisticsContract interface { SetTitle(title string) GetCheckbox() *widget.Check Add() Remove() } type queueStatistics struct { checkbox *widget.Check title string count int64 } func newQueueStatistics() QueueStatisticsContract { checkbox := widget.NewCheck(": 0", nil) checkbox.Checked = true return &queueStatistics{ checkbox: checkbox, title: "", count: 0, } } func (s *queueStatistics) SetTitle(title string) { s.title = strings.ToLower(title) s.checkbox.Text = title + ": " + strconv.FormatInt(s.count, 10) } func (s *queueStatistics) GetCheckbox() *widget.Check { return s.checkbox } func (s *queueStatistics) Add() { s.count += 1 s.formatText() } func (s *queueStatistics) Remove() { if s.count == 0 { return } s.count -= 1 s.formatText() } func (s *queueStatistics) formatText() { fyne.Do(func() { s.checkbox.Text = s.title + ": " + strconv.FormatInt(s.count, 10) s.checkbox.Refresh() }) } type queueLayoutItem struct { CanvasObject fyne.CanvasObject BlockMessageError *container.Scroll StatusMessage *canvas.Text MessageError *canvas.Text buttonPlay *widget.Button status convertor.StatusContract }