Use ratio layout for codec and preset row
This commit is contained in:
parent
896bf5b1e0
commit
4c07c7f560
|
|
@ -356,6 +356,52 @@ func TintedBar(col color.Color, body fyne.CanvasObject) fyne.CanvasObject {
|
||||||
return container.NewMax(rect, padded)
|
return container.NewMax(rect, padded)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRatioRow lays out two objects with a fixed width ratio for the left item.
|
||||||
|
func NewRatioRow(left, right fyne.CanvasObject, leftRatio float32) *fyne.Container {
|
||||||
|
return container.New(&ratioRowLayout{leftRatio: leftRatio}, left, right)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ratioRowLayout struct {
|
||||||
|
leftRatio float32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ratioRowLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
|
||||||
|
if len(objects) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ratio := clampRatio(r.leftRatio)
|
||||||
|
leftWidth := size.Width * ratio
|
||||||
|
rightWidth := size.Width - leftWidth
|
||||||
|
|
||||||
|
objects[0].Move(fyne.NewPos(0, 0))
|
||||||
|
objects[0].Resize(fyne.NewSize(leftWidth, size.Height))
|
||||||
|
objects[1].Move(fyne.NewPos(leftWidth, 0))
|
||||||
|
objects[1].Resize(fyne.NewSize(rightWidth, size.Height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ratioRowLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
|
||||||
|
if len(objects) < 2 {
|
||||||
|
return fyne.NewSize(0, 0)
|
||||||
|
}
|
||||||
|
leftMin := objects[0].MinSize()
|
||||||
|
rightMin := objects[1].MinSize()
|
||||||
|
height := leftMin.Height
|
||||||
|
if rightMin.Height > height {
|
||||||
|
height = rightMin.Height
|
||||||
|
}
|
||||||
|
return fyne.NewSize(leftMin.Width+rightMin.Width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func clampRatio(ratio float32) float32 {
|
||||||
|
if ratio < 0.1 {
|
||||||
|
return 0.1
|
||||||
|
}
|
||||||
|
if ratio > 0.9 {
|
||||||
|
return 0.9
|
||||||
|
}
|
||||||
|
return ratio
|
||||||
|
}
|
||||||
|
|
||||||
// Tappable wraps any canvas object and makes it tappable
|
// Tappable wraps any canvas object and makes it tappable
|
||||||
type Tappable struct {
|
type Tappable struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
|
||||||
86
main.go
86
main.go
|
|
@ -1,52 +1,58 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/png"
|
"log"
|
||||||
"io"
|
"net/url"
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
"fyne.io/fyne/v2/canvas"
|
"fyne.io/fyne/v2/canvas"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/data/binding"
|
||||||
"fyne.io/fyne/v2/dialog"
|
"fyne.io/fyne/v2/dialog"
|
||||||
"fyne.io/fyne/v2/driver/desktop"
|
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/storage"
|
"fyne.io/fyne/v2/storage"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
|
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/audio_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/author_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/filters_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/inspect_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/internal/app"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/benchmark"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/benchmark"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/convert"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/internal/convert/presets"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/interlace"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/enhancement"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/internal/metadata"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/modules"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/modules"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/player"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/player"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/queue"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/queue"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/sysinfo"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/thumb"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/ui"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/ui"
|
||||||
"git.leaktechnologies.dev/stu/VideoTools/internal/utils"
|
"git.leaktechnologies.dev/stu/VideoTools/internal/utils"
|
||||||
"github.com/hajimehoshi/oto"
|
"git.leaktechnologies.dev/stu/VideoTools/rip_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/settings_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/subtitles_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/thumb_module"
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/upscale_module"
|
||||||
|
|
||||||
|
"github.com/yeqown/go-qrcode/v2"
|
||||||
|
"github.com/yeqown/go-qrcode/writer/standard"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Module describes a high level tool surface that gets a tile on the menu.
|
// Module describes a high level tool surface that gets a tile on the menu.
|
||||||
|
|
@ -500,6 +506,34 @@ func openFile(path string) error {
|
||||||
return cmd.Start()
|
return cmd.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generatePixelatedQRCode() (fyne.CanvasObject, error) {
|
||||||
|
docURL := "https://docs.leaktechnologies.dev/VideoTools"
|
||||||
|
|
||||||
|
// Create chunky QR code with large pixel blocks
|
||||||
|
qrc, err := qrcode.New(docURL,
|
||||||
|
qrcode.WithQRWidth(6), // Large pixel blocks for chunky look
|
||||||
|
qrcode.WithBorderWidth(2), // Small border
|
||||||
|
qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionMedium),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate to memory
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := standard.NewWithWriter(&buf, standard.WithQRWidth(6))
|
||||||
|
if err := qrc.Save(w); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to Fyne image with pixelated look
|
||||||
|
img := canvas.NewImageFromReader(&buf, "qrcode.png")
|
||||||
|
img.FillMode = canvas.ImageFillOriginal // Keep pixelated look
|
||||||
|
img.SetMinSize(fyne.NewSize(160, 160))
|
||||||
|
|
||||||
|
return img, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *appState) showAbout() {
|
func (s *appState) showAbout() {
|
||||||
version := fmt.Sprintf("VideoTools %s", appVersion)
|
version := fmt.Sprintf("VideoTools %s", appVersion)
|
||||||
dev := "Leak Technologies"
|
dev := "Leak Technologies"
|
||||||
|
|
@ -557,6 +591,22 @@ func (s *appState) showAbout() {
|
||||||
if ltLogo != nil {
|
if ltLogo != nil {
|
||||||
logoColumn.Add(ltLogo)
|
logoColumn.Add(ltLogo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add QR code for documentation
|
||||||
|
qrCode, err := generatePixelatedQRCode()
|
||||||
|
if err != nil {
|
||||||
|
// Fallback to hyperlink if QR generation fails
|
||||||
|
docURL, _ := url.Parse("https://docs.leaktechnologies.dev/VideoTools")
|
||||||
|
fallbackLink := widget.NewHyperlink("View Documentation", docURL)
|
||||||
|
logoColumn.Add(fallbackLink)
|
||||||
|
} else {
|
||||||
|
// Add QR code with label
|
||||||
|
qrLabel := widget.NewLabel("Scan for docs")
|
||||||
|
qrLabel.Alignment = fyne.TextAlignCenter
|
||||||
|
logoColumn.Add(qrCode)
|
||||||
|
logoColumn.Add(qrLabel)
|
||||||
|
}
|
||||||
|
|
||||||
logoColumn.Add(layout.NewSpacer())
|
logoColumn.Add(layout.NewSpacer())
|
||||||
logoColumn.Add(logsLink)
|
logoColumn.Add(logsLink)
|
||||||
|
|
||||||
|
|
@ -8737,8 +8787,8 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
|
||||||
// Advanced mode options - full controls with organized sections
|
// Advanced mode options - full controls with organized sections
|
||||||
videoCodecLabel := widget.NewLabelWithStyle("Video Codec", fyne.TextAlignLeading, fyne.TextStyle{Bold: true})
|
videoCodecLabel := widget.NewLabelWithStyle("Video Codec", fyne.TextAlignLeading, fyne.TextStyle{Bold: true})
|
||||||
presetLabel := widget.NewLabelWithStyle("Encoder Preset (speed vs quality)", fyne.TextAlignLeading, fyne.TextStyle{Bold: true})
|
presetLabel := widget.NewLabelWithStyle("Encoder Preset (speed vs quality)", fyne.TextAlignLeading, fyne.TextStyle{Bold: true})
|
||||||
videoCodecRow := container.NewGridWithColumns(2, videoCodecLabel, presetLabel)
|
videoCodecRow := ui.NewRatioRow(videoCodecLabel, presetLabel, 0.3)
|
||||||
videoCodecControls := container.NewGridWithColumns(2, videoCodecContainer, encoderPresetSelect)
|
videoCodecControls := ui.NewRatioRow(videoCodecContainer, encoderPresetSelect, 0.3)
|
||||||
|
|
||||||
advancedVideoEncodingBlock = container.NewVBox(
|
advancedVideoEncodingBlock = container.NewVBox(
|
||||||
widget.NewLabelWithStyle("═══ VIDEO ENCODING ═══", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
|
widget.NewLabelWithStyle("═══ VIDEO ENCODING ═══", fyne.TextAlignCenter, fyne.TextStyle{Bold: true}),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user