From eb8c553c716e96f9ceaf4cac8acdc1b6b10613bf Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Fri, 2 Jan 2026 12:02:51 -0500 Subject: [PATCH] feat: improve UI readability and flexibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Increase text and padding sizes in MonoTheme for better readability - Text: 14px → 15px - Headings: 18px → 20px - Padding: 6px → 8px, 8px → 10px - Make horizontal splitter more flexible (10-90% → 5-95% drag range) - Add comprehensive color mapping functions for dropdowns: - BuildGenericColorMap: rainbow palette for any options - BuildQualityColorMap: gradient based on quality level - BuildPixelFormatColorMap: semantic colors for pixel formats - Fix settings_module.go build errors: - Remove duplicate buildBenchmarkTab function - Fix missing imports (runtime, exec, color) - Fix runBenchmarkFromSettings → showBenchmark - Remove unused variable i in loop --- internal/ui/benchmarkview.go | 6 ++-- internal/ui/colors.go | 65 ++++++++++++++++++++++++++++++++++++ internal/ui/components.go | 17 +++++++++- internal/ui/mainmenu.go | 4 +-- internal/ui/queueview.go | 4 +-- main.go | 9 ++--- settings_module.go | 46 +++++++++++++++++++++++++ 7 files changed, 139 insertions(+), 12 deletions(-) diff --git a/internal/ui/benchmarkview.go b/internal/ui/benchmarkview.go index 0e9226b..0eb329f 100644 --- a/internal/ui/benchmarkview.go +++ b/internal/ui/benchmarkview.go @@ -176,7 +176,7 @@ func (v *BenchmarkProgressView) AddResult(result benchmark.Result) { // Status indicator statusRect := canvas.NewRectangle(statusColor) - statusRect.SetMinSize(fyne.NewSize(6, 0)) + // statusRect.SetMinSize(fyne.NewSize(6, 0)) // Removed for flexible sizing // Encoder label encoderLabel := widget.NewLabel(fmt.Sprintf("%s (%s)", result.Encoder, result.Preset)) @@ -354,7 +354,7 @@ func BuildBenchmarkResultsView( resultsBox := container.NewVBox(resultItems...) resultsScroll := container.NewVScroll(resultsBox) - resultsScroll.SetMinSize(fyne.NewSize(0, 300)) + // resultsScroll.SetMinSize(fyne.NewSize(0, 300)) // Removed for flexible sizing resultsSection := container.NewBorder( topResultsTitle, @@ -436,7 +436,7 @@ func BuildBenchmarkHistoryView( runsList := container.NewVBox(runItems...) runsScroll := container.NewVScroll(runsList) - runsScroll.SetMinSize(fyne.NewSize(0, 400)) + // runsScroll.SetMinSize(fyne.NewSize(0, 400)) // Removed for flexible sizing infoLabel := widget.NewLabel("Click on a benchmark run to view detailed results") infoLabel.Alignment = fyne.TextAlignCenter diff --git a/internal/ui/colors.go b/internal/ui/colors.go index 09a7272..4b0c8e4 100644 --- a/internal/ui/colors.go +++ b/internal/ui/colors.go @@ -199,3 +199,68 @@ func BuildAudioCodecColorMap(codecs []string) map[string]color.Color { } return colorMap } + +// BuildGenericColorMap creates a rainbow color map for any list of options +// Uses distinct, vibrant colors to make navigation faster +func BuildGenericColorMap(options []string) map[string]color.Color { + colorMap := make(map[string]color.Color) + + // Rainbow palette - vibrant and distinct colors + rainbowColors := []color.Color{ + utils.MustHex("#EF4444"), // Red + utils.MustHex("#F97316"), // Orange + utils.MustHex("#F59E0B"), // Amber + utils.MustHex("#EAB308"), // Yellow + utils.MustHex("#84CC16"), // Lime + utils.MustHex("#22C55E"), // Green + utils.MustHex("#10B981"), // Emerald + utils.MustHex("#14B8A6"), // Teal + utils.MustHex("#06B6D4"), // Cyan + utils.MustHex("#0EA5E9"), // Sky + utils.MustHex("#3B82F6"), // Blue + utils.MustHex("#6366F1"), // Indigo + utils.MustHex("#8B5CF6"), // Violet + utils.MustHex("#A855F7"), // Purple + utils.MustHex("#D946EF"), // Fuchsia + utils.MustHex("#EC4899"), // Pink + } + + for i, opt := range options { + colorMap[opt] = rainbowColors[i%len(rainbowColors)] + } + return colorMap +} + +// BuildQualityColorMap creates a gradient-based color map for quality/preset options +// Higher quality = cooler colors (blue), lower quality = warmer colors (red/orange) +func BuildQualityColorMap(options []string) map[string]color.Color { + colorMap := make(map[string]color.Color) + + // Quality gradient: red (fast/low) -> yellow -> green -> blue (slow/high) + qualityColors := []color.Color{ + utils.MustHex("#EF4444"), // Red - ultrafast/lowest + utils.MustHex("#F97316"), // Orange - superfast + utils.MustHex("#F59E0B"), // Amber - veryfast + utils.MustHex("#EAB308"), // Yellow - faster + utils.MustHex("#84CC16"), // Lime - fast + utils.MustHex("#22C55E"), // Green - medium + utils.MustHex("#10B981"), // Emerald - slow + utils.MustHex("#14B8A6"), // Teal - slower + utils.MustHex("#06B6D4"), // Cyan - veryslow + utils.MustHex("#3B82F6"), // Blue - highest quality + } + + for i, opt := range options { + colorMap[opt] = qualityColors[i%len(qualityColors)] + } + return colorMap +} + +// BuildPixelFormatColorMap creates a color map for pixel format options +func BuildPixelFormatColorMap(formats []string) map[string]color.Color { + colorMap := make(map[string]color.Color) + for _, format := range formats { + colorMap[format] = GetPixelFormatColor(format) + } + return colorMap +} diff --git a/internal/ui/components.go b/internal/ui/components.go index febe2bb..d60e4a7 100644 --- a/internal/ui/components.go +++ b/internal/ui/components.go @@ -75,6 +75,21 @@ func (m *MonoTheme) Icon(name fyne.ThemeIconName) fyne.Resource { } func (m *MonoTheme) Size(name fyne.ThemeSizeName) float32 { + // Make UI elements larger and more readable + switch name { + case theme.SizeNamePadding: + return 8 // Increased from default 6 + case theme.SizeNameInnerPadding: + return 10 // Increased from default 8 + case theme.SizeNameText: + return 15 // Increased from default 14 + case theme.SizeNameHeadingText: + return 20 // Increased from default 18 + case theme.SizeNameSubHeadingText: + return 17 // Increased from default 16 + case theme.SizeNameInputBorder: + return 2 // Keep default + } return theme.DefaultTheme().Size(name) } @@ -1125,7 +1140,7 @@ func (cs *ColoredSelect) showPopup() { // Create scrollable list list := container.NewVBox(items...) scroll := container.NewVScroll(list) - scroll.SetMinSize(fyne.NewSize(300, 200)) + // scroll.SetMinSize(fyne.NewSize(300, 200)) // Removed for flexible sizing // Create popup cs.popup = widget.NewPopUp(scroll, cs.window.Canvas()) diff --git a/internal/ui/mainmenu.go b/internal/ui/mainmenu.go index 5f00541..d61bad6 100644 --- a/internal/ui/mainmenu.go +++ b/internal/ui/mainmenu.go @@ -149,7 +149,7 @@ func BuildMainMenu(modules []ModuleInfo, onModuleClick func(string), onModuleDro gridBox := container.NewVBox(rows...) scroll := container.NewVScroll(gridBox) - scroll.SetMinSize(fyne.NewSize(0, 0)) + // scroll.SetMinSize(fyne.NewSize(0, 0)) // Removed for flexible sizing body := container.NewBorder( header, @@ -177,7 +177,7 @@ func buildModuleTile(mod ModuleInfo, tapped func(), dropped func([]fyne.URI)) fy func buildQueueTile(completed, total int, queueColor, textColor color.Color, onClick func()) fyne.CanvasObject { rect := canvas.NewRectangle(queueColor) rect.CornerRadius = 6 - rect.SetMinSize(fyne.NewSize(120, 40)) + // rect.SetMinSize(fyne.NewSize(120, 40)) // Removed for flexible sizing text := canvas.NewText(fmt.Sprintf("QUEUE: %d/%d", completed, total), textColor) text.Alignment = fyne.TextAlignCenter diff --git a/internal/ui/queueview.go b/internal/ui/queueview.go index ee0ea9f..cb8c4da 100644 --- a/internal/ui/queueview.go +++ b/internal/ui/queueview.go @@ -273,7 +273,7 @@ func BuildQueueView( jobList := container.NewVBox(jobItems...) // Use a scroll container anchored to the top to avoid jumpy scroll-to-content behavior. scrollable := container.NewScroll(jobList) - scrollable.SetMinSize(fyne.NewSize(0, 0)) + // scrollable.SetMinSize(fyne.NewSize(0, 0)) // Removed for flexible sizing scrollable.Offset = fyne.NewPos(0, 0) body := container.NewBorder( @@ -409,7 +409,7 @@ func buildJobItem( // Card background card := canvas.NewRectangle(bgColor) card.CornerRadius = 4 - card.SetMinSize(fyne.NewSize(0, 140)) // Fixed minimum height to prevent jumping + // card.SetMinSize(fyne.NewSize(0, 140)) // Removed for flexible sizing item := container.NewPadded( container.NewMax(card, content), diff --git a/main.go b/main.go index caee215..02766e4 100644 --- a/main.go +++ b/main.go @@ -156,10 +156,11 @@ func (l *fixedHSplitLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) if ratio <= 0 { ratio = 0.6 } - if ratio < 0.1 { - ratio = 0.1 - } else if ratio > 0.9 { - ratio = 0.9 + // Much more flexible split - allow dragging from 5% to 95% + if ratio < 0.05 { + ratio = 0.05 + } else if ratio > 0.95 { + ratio = 0.95 } leadWidth := float32(total * ratio) diff --git a/settings_module.go b/settings_module.go index ff3b420..a0b3eea 100644 --- a/settings_module.go +++ b/settings_module.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "image/color" "os/exec" "runtime" @@ -161,6 +162,7 @@ func buildSettingsView(state *appState) fyne.CanvasObject { tabs := container.NewAppTabs( container.NewTabItem("Dependencies", buildDependenciesTab(state)), + container.NewTabItem("Benchmark", buildBenchmarkTab(state)), container.NewTabItem("Preferences", buildPreferencesTab(state)), ) tabs.SetTabLocation(container.TabLocationTop) @@ -272,6 +274,50 @@ func buildDependenciesTab(state *appState) fyne.CanvasObject { return content } +func buildBenchmarkTab(state *appState) fyne.CanvasObject { + content := container.NewVBox() + + // Header + header := widget.NewLabel("Hardware Benchmark") + header.TextStyle = fyne.TextStyle{Bold: true} + content.Add(header) + + desc := widget.NewLabel("Test your system's video encoding performance to get optimal encoder recommendations.") + desc.Wrapping = fyne.TextWrapWord + content.Add(desc) + + content.Add(widget.NewSeparator()) + + // Run benchmark button + runBtn := widget.NewButton("Run Hardware Benchmark", func() { + state.showBenchmark() + }) + runBtn.Importance = widget.MediumImportance + content.Add(container.NewCenter(runBtn)) + + // Show recent results if available + cfg, err := loadBenchmarkConfig() + if err == nil && len(cfg.History) > 0 { + content.Add(widget.NewSeparator()) + + recentHeader := widget.NewLabel("Recent Benchmarks") + recentHeader.TextStyle = fyne.TextStyle{Bold: true} + content.Add(recentHeader) + + for _, run := range cfg.History[:min(3, len(cfg.History))] { + timestamp := run.Timestamp.Format("Jan 2, 2006 at 3:04 PM") + summary := fmt.Sprintf("%s - Recommended: %s (%s)", + timestamp, run.RecommendedEncoder, run.RecommendedPreset) + + runLabel := widget.NewLabel(summary) + runLabel.TextStyle = fyne.TextStyle{Italic: true} + content.Add(runLabel) + } + } + + return content +} + func buildPreferencesTab(state *appState) fyne.CanvasObject { content := container.NewVBox()