summaryrefslogtreecommitdiff
path: root/internal/gui
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-18 08:34:16 +0300
committerPaul Buetow <paul@buetow.org>2025-07-18 08:34:16 +0300
commite2f45921c45c9322c2ddb679d0511ba20772dcae (patch)
tree85e13d7d4127bd1fdc4821427782475095c6f289 /internal/gui
parent85ee3559fcdee46a21c4e9a5ef9ec519d997c447 (diff)
gui improvements
Diffstat (limited to 'internal/gui')
-rw-r--r--internal/gui/app.go91
-rw-r--r--internal/gui/audio_player.go18
2 files changed, 88 insertions, 21 deletions
diff --git a/internal/gui/app.go b/internal/gui/app.go
index 46141d6..2caffe4 100644
--- a/internal/gui/app.go
+++ b/internal/gui/app.go
@@ -15,6 +15,7 @@ import (
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/storage"
+ "fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/sashabaranov/go-openai"
@@ -192,9 +193,18 @@ func (a *Application) setupUI() {
a.window.Canvas().Unfocus()
}
- a.submitButton = widget.NewButton("Generate (g)", a.onSubmit)
- a.prevWordBtn = widget.NewButton("◀ Prev (←)", a.onPrevWord)
- a.nextWordBtn = widget.NewButton("Next (→) ▶", a.onNextWord)
+ // Create navigation buttons with tooltips
+ a.submitButton = widget.NewButtonWithIcon("", theme.ConfirmIcon(), a.onSubmit)
+ submitLabel := widget.NewLabelWithStyle("Generate (g)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ submitBtn := container.NewVBox(a.submitButton, submitLabel)
+
+ a.prevWordBtn = widget.NewButtonWithIcon("", theme.NavigateBackIcon(), a.onPrevWord)
+ prevLabel := widget.NewLabelWithStyle("Previous (←)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ prevBtn := container.NewVBox(a.prevWordBtn, prevLabel)
+
+ a.nextWordBtn = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), a.onNextWord)
+ nextLabel := widget.NewLabelWithStyle("Next (→)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ nextBtn := container.NewVBox(a.nextWordBtn, nextLabel)
// Create a grid layout for inputs
inputGrid := container.New(layout.NewGridLayout(2),
@@ -204,8 +214,8 @@ func (a *Application) setupUI() {
inputSection := container.NewBorder(
nil, nil,
- a.prevWordBtn,
- container.NewHBox(a.submitButton, a.nextWordBtn),
+ prevBtn,
+ container.NewHBox(submitBtn, nextBtn),
inputGrid,
)
@@ -269,27 +279,44 @@ func (a *Application) setupUI() {
imageSection,
)
- // Create action buttons
- a.keepButton = widget.NewButton("New Word (n)", a.onKeepAndContinue)
- a.regenerateImageBtn = widget.NewButton("Regenerate Image (i)", a.onRegenerateImage)
- a.regenerateRandomImageBtn = widget.NewButton("Random Image (m)", a.onRegenerateRandomImage)
- a.regenerateAudioBtn = widget.NewButton("Regenerate Audio (a)", a.onRegenerateAudio)
- a.regenerateAllBtn = widget.NewButton("Regenerate All (r)", a.onRegenerateAll)
- a.deleteButton = widget.NewButton("Delete (d)", a.onDelete)
+ // Create action buttons with icons and tooltips
+ a.keepButton = widget.NewButtonWithIcon("", theme.DocumentCreateIcon(), a.onKeepAndContinue)
+ keepLabel := widget.NewLabelWithStyle("New Word (n)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ keepBtn := container.NewVBox(a.keepButton, keepLabel)
+
+ a.regenerateImageBtn = widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), a.onRegenerateImage)
+ imageLabel := widget.NewLabelWithStyle("Regenerate Image (i)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ regenerateImageBtn := container.NewVBox(a.regenerateImageBtn, imageLabel)
+
+ a.regenerateRandomImageBtn = widget.NewButtonWithIcon("", theme.MediaPhotoIcon(), a.onRegenerateRandomImage)
+ randomLabel := widget.NewLabelWithStyle("Random Image (m)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ regenerateRandomBtn := container.NewVBox(a.regenerateRandomImageBtn, randomLabel)
+
+ a.regenerateAudioBtn = widget.NewButtonWithIcon("", theme.MediaPlayIcon(), a.onRegenerateAudio)
+ audioLabel := widget.NewLabelWithStyle("Regenerate Audio (a)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ regenerateAudioBtn := container.NewVBox(a.regenerateAudioBtn, audioLabel)
+
+ a.regenerateAllBtn = widget.NewButtonWithIcon("", theme.ViewFullScreenIcon(), a.onRegenerateAll)
+ allLabel := widget.NewLabelWithStyle("Regenerate All (r)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ regenerateAllBtn := container.NewVBox(a.regenerateAllBtn, allLabel)
+
+ a.deleteButton = widget.NewButtonWithIcon("", theme.DeleteIcon(), a.onDelete)
a.deleteButton.Importance = widget.DangerImportance
+ deleteLabel := widget.NewLabelWithStyle("Delete (d)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true})
+ deleteBtn := container.NewVBox(a.deleteButton, deleteLabel)
// Initially disable action buttons
a.setActionButtonsEnabled(false)
actionSection := container.NewHBox(
- a.keepButton,
+ keepBtn,
layout.NewSpacer(),
- a.deleteButton,
+ deleteBtn,
widget.NewSeparator(),
- a.regenerateImageBtn,
- a.regenerateRandomImageBtn,
- a.regenerateAudioBtn,
- a.regenerateAllBtn,
+ regenerateImageBtn,
+ regenerateRandomBtn,
+ regenerateAudioBtn,
+ regenerateAllBtn,
)
// Create status section
@@ -344,6 +371,8 @@ func (a *Application) setupUI() {
// Run starts the GUI application
func (a *Application) Run() {
+ // Focus the Bulgarian word input on startup
+ a.window.Canvas().Focus(a.wordInput)
a.window.ShowAndRun()
}
@@ -1237,6 +1266,12 @@ func (a *Application) setupKeyboardShortcuts() {
return
}
+ // Handle Tab key for custom focus navigation
+ if ev.Name == fyne.KeyTab {
+ a.handleTabNavigation()
+ return
+ }
+
// Check if input field is focused
focused := a.window.Canvas().Focused()
isInputFocused := focused == a.wordInput || focused == a.imagePromptEntry || focused == a.translationEntry
@@ -1255,6 +1290,26 @@ func (a *Application) setupKeyboardShortcuts() {
})
}
+// handleTabNavigation manages custom Tab navigation order
+func (a *Application) handleTabNavigation() {
+ focused := a.window.Canvas().Focused()
+
+ switch focused {
+ case a.wordInput:
+ // From Bulgarian -> English
+ a.window.Canvas().Focus(a.translationEntry)
+ case a.translationEntry:
+ // From English -> Image prompt
+ a.window.Canvas().Focus(a.imagePromptEntry)
+ case a.imagePromptEntry:
+ // From Image prompt -> Bulgarian (cycle back)
+ a.window.Canvas().Focus(a.wordInput)
+ default:
+ // If nothing focused, start with Bulgarian
+ a.window.Canvas().Focus(a.wordInput)
+ }
+}
+
// handleShortcutKey handles the actual shortcut action
func (a *Application) handleShortcutKey(key fyne.KeyName) {
// Don't process if we're in delete confirmation mode
diff --git a/internal/gui/audio_player.go b/internal/gui/audio_player.go
index f36eddf..63428bd 100644
--- a/internal/gui/audio_player.go
+++ b/internal/gui/audio_player.go
@@ -9,6 +9,7 @@ import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
+ "fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
@@ -39,10 +40,21 @@ func NewAudioPlayer() *AudioPlayer {
p.playButton.Disable()
p.stopButton.Disable()
- // Create container
- p.container = container.NewHBox(
+ // Create containers with tooltips
+ playContainer := container.NewVBox(
p.playButton,
+ widget.NewLabelWithStyle("Play (p)", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}),
+ )
+
+ stopContainer := container.NewVBox(
p.stopButton,
+ widget.NewLabelWithStyle("Stop", fyne.TextAlignCenter, fyne.TextStyle{Italic: true}),
+ )
+
+ // Create main container
+ p.container = container.NewHBox(
+ playContainer,
+ stopContainer,
layout.NewSpacer(),
p.statusLabel,
)
@@ -164,7 +176,7 @@ func (p *AudioPlayer) startPlayback() error {
// Playback finished normally
fyne.Do(func() {
p.isPlaying = false
- p.playButton.SetText("▶ Play (p)")
+ p.playButton.SetIcon(theme.MediaPlayIcon())
p.stopButton.Disable()
p.statusLabel.SetText("Finished: " + filepath.Base(p.audioFile))
})