From 0885d69015731be7cc574593619e08e8b5e1ed1f Mon Sep 17 00:00:00 2001 From: oxpoe Date: Tue, 13 Oct 2026 07:32:06 +0700 Subject: [PATCH] Dialog: tombol tutup + Kembali, isi bisa di-scroll, ukuran mengikuti window - Tombol X di kanan atas tiap dialog + tombol Back di modal pencarian ikon - Isi dialog dibungkus scroll: Fyne tidak bisa mengecilkan dialog di bawah MinSize konten, jadi di layar ber-penskalaan besar tombol bawah tadinya bisa terpotong - Ukuran dialog dibatasi 90% lebar / 85% tinggi window --- internal/ui/dialog_executable.go | 8 ++++---- internal/ui/dialog_icon.go | 7 +++---- internal/ui/dialog_webapp.go | 9 ++++----- internal/ui/style.go | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/internal/ui/dialog_executable.go b/internal/ui/dialog_executable.go index b159a3f..96af916 100644 --- a/internal/ui/dialog_executable.go +++ b/internal/ui/dialog_executable.go @@ -100,7 +100,8 @@ func (ui *app) showExecutableDialog() { widget.NewFormItem(T("field_name"), nameEntry), widget.NewFormItem(T("field_category"), category), ) - content := container.NewVBox( + content := container.NewVScroll(container.NewVBox( + closeRow(func() { d.Hide() }), form, widget.NewSeparator(), sectionTitle(T("section_location")), @@ -110,11 +111,10 @@ func (ui *app) showExecutableDialog() { container.NewHBox(logoBox(newLogo(), 20), spacer(), widget.NewButton(T("cancel"), func() { d.Hide() }), install), - ) + )) d = dialog.NewCustom(T("new_exec_title"), "", content, ui.win) - d.Resize(fyne.NewSize(560, 470)) - d.Show() + showDialog(d, ui.win, 560, 520) } // pickFile membuka file picker dan mengirim path absolut ke onPick. diff --git a/internal/ui/dialog_icon.go b/internal/ui/dialog_icon.go index f96e404..bee8a94 100644 --- a/internal/ui/dialog_icon.go +++ b/internal/ui/dialog_icon.go @@ -49,10 +49,10 @@ func (ui *app) showIconSearch(query string, onPick func(icon.Result, []byte)) { entry.OnSubmitted = func(string) { search() } content := container.NewBorder( - entry, + container.NewVBox(closeRow(func() { d.Hide() }), entry), container.NewBorder(nil, nil, status, container.NewHBox( - widget.NewButton(T("cancel"), func() { d.Hide() }), + widget.NewButtonWithIcon(T("back"), theme.NavigateBackIcon(), func() { d.Hide() }), widget.NewButtonWithIcon(T("search"), theme.SearchIcon(), search), )), nil, nil, @@ -60,8 +60,7 @@ func (ui *app) showIconSearch(query string, onPick func(icon.Result, []byte)) { ) d = dialog.NewCustom(T("icon_search_title"), "", content, ui.win) - d.Resize(fyne.NewSize(560, 460)) - d.Show() + showDialog(d, ui.win, 560, 470) search() } diff --git a/internal/ui/dialog_webapp.go b/internal/ui/dialog_webapp.go index b4b0ffe..fe78ab0 100644 --- a/internal/ui/dialog_webapp.go +++ b/internal/ui/dialog_webapp.go @@ -5,7 +5,6 @@ import ( "path/filepath" "strings" - "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" @@ -106,7 +105,8 @@ func (ui *app) showWebAppDialog() { widget.NewFormItem(T("field_icon"), container.NewBorder(nil, nil, nil, container.NewHBox(onlineIcon, browseIcon), iconLabel)), ) - content := container.NewVBox( + content := container.NewVScroll(container.NewVBox( + closeRow(func() { d.Hide() }), form, widget.NewSeparator(), sectionTitle(T("section_location")), @@ -116,11 +116,10 @@ func (ui *app) showWebAppDialog() { container.NewHBox(logoBox(newLogo(), 20), spacer(), widget.NewButton(T("cancel"), func() { d.Hide() }), install), - ) + )) d = dialog.NewCustom(T("new_web_title"), "", content, ui.win) - d.Resize(fyne.NewSize(560, 470)) - d.Show() + showDialog(d, ui.win, 560, 520) } func browserNames(list []browser.Browser) []string { diff --git a/internal/ui/style.go b/internal/ui/style.go index ad298cd..e7b1fa3 100644 --- a/internal/ui/style.go +++ b/internal/ui/style.go @@ -7,6 +7,7 @@ import ( "fyne.io/fyne/v2" "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/theme" @@ -118,5 +119,23 @@ func logoBox(image *canvas.Image, size float32) fyne.CanvasObject { return container.NewGridWrap(fyne.NewSize(size, size), image) } +// closeRow menempatkan tombol tutup di kanan atas isi dialog, supaya +// selalu ada jalan keluar yang terlihat walau tombol bawah terpotong. +func closeRow(hide func()) fyne.CanvasObject { + return container.NewHBox(spacer(), iconButton(theme.CancelIcon(), hide)) +} + +// showDialog menampilkan dialog dengan ukuran yang disesuaikan ke window. +// Isi dialog sebaiknya dibungkus VScroll supaya MinSize-nya kecil (Fyne tidak +// bisa mengecilkan dialog di bawah MinSize konten). +func showDialog(d *dialog.CustomDialog, win fyne.Window, width, height float32) { + size := win.Canvas().Size() + d.Resize(fyne.NewSize( + fyne.Min(width, size.Width*0.9), + fyne.Min(height, size.Height*0.85), + )) + d.Show() +} + // spacer adalah pengisi ruang kosong. func spacer() fyne.CanvasObject { return layout.NewSpacer() }