Files
oxpoe deaa30689c Tooltip hint, loading bar, edit shortcut, export/import .lazy
- Keterangan tombol saat hover: baris hint di footer window dan di dalam dialog
  (bukan popup: overlay Fyne menelan klik pertama, tombol jadi perlu 2x klik)
- Dialog proses sekarang pakai progress bar berjalan (bukan spinner diam)
- Tombol edit per shortcut: ganti binary/URL, ikon (file/online), nama, kategori,
  dan lokasi; berkas .desktop + salinan Desktop ditulis ulang, berkas lama dibuang,
  jenis aplikasi dideteksi ulang, binary lama dihapus kalau nama berubah
- Export/Import daftar shortcut ke berkas SQLite .lazy (driver murni Go modernc),
  skema + meta format versi, impor tidak menimpa shortcut yang sudah ada
- Tes: detect kind, edit (rename/ganti binary/ikon/target), db roundtrip, merge impor,
  tooltip (hint muncul/hilang + klik tetap sampai ke tombol), semua paket hijau
- README: bagian backup + hint tombol
2026-10-13 09:12:39 +07:00

108 lines
2.6 KiB
Go

package ui
import (
"sync"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/widget"
)
// Keterangan tombol muncul di satu baris hint (bawah window atau dalam dialog),
// bukan sebagai popup: popup Fyne selalu jadi overlay, dan selama overlay ada
// semua klik ke konten di bawahnya tidak diteruskan (tombol jadi perlu 2x klik).
var (
hintMu sync.Mutex
hintTarget *canvas.Text
)
// pushHintTarget mengarahkan keterangan hover ke label tertentu (dipakai dialog).
// Fungsi yang dikembalikan mengembalikan target sebelumnya.
func pushHintTarget(label *canvas.Text) func() {
hintMu.Lock()
previous := hintTarget
hintTarget = label
hintMu.Unlock()
return func() {
hintMu.Lock()
hintTarget = previous
hintMu.Unlock()
}
}
func showHint(text string) {
hintMu.Lock()
target := hintTarget
hintMu.Unlock()
if target == nil || text == "" {
return
}
target.Text = text
target.Refresh()
}
// clearHint menghapus hint hanya kalau isinya memang milik tombol ini.
func clearHint(text string) {
hintMu.Lock()
target := hintTarget
hintMu.Unlock()
if target == nil || target.Text != text {
return
}
target.Text = ""
target.Refresh()
}
// tipButton adalah tombol yang menampilkan fungsinya saat disorot mouse.
type tipButton struct {
widget.Button
tip string
}
// newButton membuat tombol (dengan ikon kalau diberikan) plus keterangan hover.
func newButton(text string, icon fyne.Resource, tip string, importance widget.Importance, tapped func()) *tipButton {
button := &tipButton{tip: tip}
button.Text = text
button.Icon = icon
button.Importance = importance
button.OnTapped = tapped
button.ExtendBaseWidget(button)
return button
}
// newIconButton adalah tombol ikon saja (tanpa teks), gaya datar.
func newIconButton(icon fyne.Resource, tip string, tapped func()) *tipButton {
return newButton("", icon, tip, widget.LowImportance, tapped)
}
func (b *tipButton) MouseIn(event *desktop.MouseEvent) {
b.Button.MouseIn(event)
showHint(b.tip)
}
func (b *tipButton) MouseOut() {
b.Button.MouseOut()
clearHint(b.tip)
}
// showLoading menampilkan dialog proses dengan progress bar yang berjalan,
// dan mengembalikan fungsi untuk menutupnya.
func (ui *app) showLoading(title, message string) func() {
bar := widget.NewProgressBarInfinite()
var d *dialog.CustomDialog
d = dialog.NewCustomWithoutButtons(title, container.NewBorder(
container.NewVBox(logoBox(newLogo(), 22), muted(message)),
nil, nil, nil,
bar,
), ui.win)
showDialog(d, ui.win, 420, 170)
return d.Hide
}