API Dialogs
Gambaran Umum
Section titled “Gambaran Umum”API Dialogs menyediakan metode untuk menampilkan dialog file native dan dialog pesan. Akses dialog melalui manajer app.Dialog.
Jenis Dialog:
- Dialog File - Dialog Buka dan Simpan
- Dialog Pesan - Dialog Info, Error, Warning, dan Question
Semua dialog adalah dialog OS native yang sesuai dengan tampilan dan nuansa platform.
Mengakses Dialog
Section titled “Mengakses Dialog”Dialog diakses melalui manajer app.Dialog:
app.Dialog.OpenFile()app.Dialog.SaveFile()app.Dialog.Info()app.Dialog.Question()app.Dialog.Warning()app.Dialog.Error()Dialog File
Section titled “Dialog File”OpenFile()
Section titled “OpenFile()”Membuat dialog buka file.
func (dm *DialogManager) OpenFile() *OpenFileDialogStructContoh:
dialog := app.Dialog.OpenFile()Metode OpenFileDialogStruct
Section titled “Metode OpenFileDialogStruct”SetTitle()
Section titled “SetTitle()”Mengatur judul dialog.
func (d *OpenFileDialogStruct) SetTitle(title string) *OpenFileDialogStructContoh:
dialog.SetTitle("Select Image")AddFilter()
Section titled “AddFilter()”Menambahkan filter tipe file.
func (d *OpenFileDialogStruct) AddFilter(displayName, pattern string) *OpenFileDialogStructParameter:
displayName- Deskripsi filter yang ditampilkan ke pengguna (mis., “Images”, “Documents”)pattern- Daftar ekstensi yang dipisahkan titik koma (mis., “.png;.jpg”)
Contoh:
dialog.AddFilter("Images", "*.png;*.jpg;*.gif"). AddFilter("Documents", "*.pdf;*.docx"). AddFilter("All Files", "*.*")SetDirectory()
Section titled “SetDirectory()”Mengatur direktori awal.
func (d *OpenFileDialogStruct) SetDirectory(directory string) *OpenFileDialogStructContoh:
homeDir, _ := os.UserHomeDir()dialog.SetDirectory(homeDir)CanChooseDirectories()
Section titled “CanChooseDirectories()”Mengaktifkan atau menonaktifkan pemilihan direktori.
func (d *OpenFileDialogStruct) CanChooseDirectories(canChooseDirectories bool) *OpenFileDialogStructContoh (pemilihan folder):
// Pilih folder alih-alih filepath, err := app.Dialog.OpenFile(). SetTitle("Select Folder"). CanChooseDirectories(true). CanChooseFiles(false). PromptForSingleSelection()CanChooseFiles()
Section titled “CanChooseFiles()”Mengaktifkan atau menonaktifkan pemilihan file.
func (d *OpenFileDialogStruct) CanChooseFiles(canChooseFiles bool) *OpenFileDialogStructCanCreateDirectories()
Section titled “CanCreateDirectories()”Mengaktifkan atau menonaktifkan pembuatan direktori baru.
func (d *OpenFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *OpenFileDialogStructShowHiddenFiles()
Section titled “ShowHiddenFiles()”Menampilkan atau menyembunyikan file tersembunyi.
func (d *OpenFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialogStructAttachToWindow()
Section titled “AttachToWindow()”Melampirkan dialog ke window tertentu.
func (d *OpenFileDialogStruct) AttachToWindow(window Window) *OpenFileDialogStructPromptForSingleSelection()
Section titled “PromptForSingleSelection()”Menampilkan dialog dan mengembalikan file yang dipilih.
func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error)Mengembalikan:
string- Path file yang dipilih. Anggap string kosong sebagai “tidak ada pilihan” (implementasi platform dapat mengembalikan string kosong atau error non-nil saat pembatalan tergantung OS).error- Non-nil jika dialog gagal ditampilkan.
Contoh:
path, err := app.Dialog.OpenFile(). SetTitle("Select Image"). AddFilter("Images", "*.png;*.jpg;*.gif"). PromptForSingleSelection()
if err != nil { // Dialog gagal ditampilkan (jarang). return}if path == "" { // Pengguna membatalkan. return}
// Gunakan file yang dipilihprocessFile(path)PromptForMultipleSelection()
Section titled “PromptForMultipleSelection()”Menampilkan dialog dan mengembalikan beberapa file yang dipilih.
func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error)Mengembalikan:
[]string- Array path file yang dipiliherror- Error jika dialog gagal
Contoh:
paths, err := app.Dialog.OpenFile(). SetTitle("Select Images"). AddFilter("Images", "*.png;*.jpg"). PromptForMultipleSelection()
if err != nil { return}
for _, path := range paths { processFile(path)}SaveFile()
Section titled “SaveFile()”Membuat dialog simpan file.
func (dm *DialogManager) SaveFile() *SaveFileDialogStructContoh:
dialog := app.Dialog.SaveFile()Metode SaveFileDialogStruct
Section titled “Metode SaveFileDialogStruct”SetTitle()
Section titled “SetTitle()”Mengatur judul dialog.
func (d *SaveFileDialogStruct) SetTitle(title string) *SaveFileDialogStructSetFilename()
Section titled “SetFilename()”Mengatur nama file default.
func (d *SaveFileDialogStruct) SetFilename(filename string) *SaveFileDialogStructContoh:
dialog.SetFilename("document.pdf")AddFilter()
Section titled “AddFilter()”Menambahkan filter tipe file.
func (d *SaveFileDialogStruct) AddFilter(displayName, pattern string) *SaveFileDialogStructContoh:
dialog.AddFilter("PDF Document", "*.pdf"). AddFilter("Text Document", "*.txt")SetDirectory()
Section titled “SetDirectory()”Mengatur direktori awal.
func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStructAttachToWindow()
Section titled “AttachToWindow()”Melampirkan dialog ke window tertentu.
func (d *SaveFileDialogStruct) AttachToWindow(window Window) *SaveFileDialogStructPromptForSingleSelection()
Section titled “PromptForSingleSelection()”Menampilkan dialog dan mengembalikan path simpan.
func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error)Contoh:
path, err := app.Dialog.SaveFile(). SetTitle("Save Document"). SetFilename("untitled.pdf"). AddFilter("PDF Document", "*.pdf"). PromptForSingleSelection()
if err != nil { // Pengguna membatalkan return}
// Simpan ke path yang dipilihsaveDocument(path)Pemilihan Folder
Section titled “Pemilihan Folder”Tidak ada SelectFolderDialog terpisah. Gunakan OpenFile() dengan opsi direktori:
path, err := app.Dialog.OpenFile(). SetTitle("Select Output Folder"). CanChooseDirectories(true). CanChooseFiles(false). PromptForSingleSelection()
if err != nil { // Pengguna membatalkan return}
// Gunakan folder yang dipilihoutputDir = pathDialog Pesan
Section titled “Dialog Pesan”Semua dialog pesan mengembalikan *MessageDialog dan berbagi metode yang sama.
Info()
Section titled “Info()”Membuat dialog informasi.
func (dm *DialogManager) Info() *MessageDialogContoh:
app.Dialog.Info(). SetTitle("Success"). SetMessage("File saved successfully!"). Show()Error()
Section titled “Error()”Membuat dialog error.
func (dm *DialogManager) Error() *MessageDialogContoh:
app.Dialog.Error(). SetTitle("Error"). SetMessage("Failed to save file: " + err.Error()). Show()Warning()
Section titled “Warning()”Membuat dialog peringatan.
func (dm *DialogManager) Warning() *MessageDialogContoh:
app.Dialog.Warning(). SetTitle("Warning"). SetMessage("This action cannot be undone."). Show()Question()
Section titled “Question()”Membuat dialog pertanyaan dengan tombol kustom.
func (dm *DialogManager) Question() *MessageDialogContoh:
dialog := app.Dialog.Question(). SetTitle("Confirm"). SetMessage("Do you want to save changes?")
save := dialog.AddButton("Save")save.OnClick(func() { saveDocument()})
dontSave := dialog.AddButton("Don't Save")dontSave.OnClick(func() { // Lanjutkan tanpa menyimpan})
cancel := dialog.AddButton("Cancel")cancel.OnClick(func() { // Tidak melakukan apa-apa})
dialog.SetDefaultButton(save)dialog.SetCancelButton(cancel)dialog.Show()Metode MessageDialog
Section titled “Metode MessageDialog”SetTitle()
Section titled “SetTitle()”Mengatur judul dialog.
func (d *MessageDialog) SetTitle(title string) *MessageDialogSetMessage()
Section titled “SetMessage()”Mengatur pesan dialog.
func (d *MessageDialog) SetMessage(message string) *MessageDialogSetIcon()
Section titled “SetIcon()”Mengatur ikon kustom untuk dialog.
func (d *MessageDialog) SetIcon(icon []byte) *MessageDialogAddButton()
Section titled “AddButton()”Menambahkan tombol ke dialog dan mengembalikan tombol untuk konfigurasi.
func (d *MessageDialog) AddButton(label string) *ButtonMengembalikan: *Button - Instance tombol untuk konfigurasi lebih lanjut
Contoh:
button := dialog.AddButton("OK")button.OnClick(func() { // Tangani klik})SetDefaultButton()
Section titled “SetDefaultButton()”Mengatur tombol mana yang menjadi default (diaktifkan dengan menekan Enter).
func (d *MessageDialog) SetDefaultButton(button *Button) *MessageDialogContoh:
yes := dialog.AddButton("Yes")no := dialog.AddButton("No")dialog.SetDefaultButton(yes)SetCancelButton()
Section titled “SetCancelButton()”Mengatur tombol mana yang menjadi tombol batal (diaktifkan dengan menekan Escape).
func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialogContoh:
ok := dialog.AddButton("OK")cancel := dialog.AddButton("Cancel")dialog.SetCancelButton(cancel)AttachToWindow()
Section titled “AttachToWindow()”Melampirkan dialog ke window tertentu.
func (d *MessageDialog) AttachToWindow(window Window) *MessageDialogShow()
Section titled “Show()”Menampilkan dialog. Callback tombol menangani respons pengguna.
func (d *MessageDialog) Show()Catatan: Show() tidak mengembalikan nilai. Gunakan callback tombol untuk menangani respons pengguna.
Metode Button
Section titled “Metode Button”OnClick()
Section titled “OnClick()”Mengatur fungsi callback saat tombol diklik.
func (b *Button) OnClick(callback func()) *ButtonSetAsDefault()
Section titled “SetAsDefault()”Menandai tombol ini sebagai tombol default.
func (b *Button) SetAsDefault() *ButtonSetAsCancel()
Section titled “SetAsCancel()”Menandai tombol ini sebagai tombol batal.
func (b *Button) SetAsCancel() *ButtonContoh Lengkap
Section titled “Contoh Lengkap”Contoh Pemilihan File
Section titled “Contoh Pemilihan File”type FileService struct { app *application.App}
func (s *FileService) OpenImage() (string, error) { path, err := s.app.Dialog.OpenFile(). SetTitle("Select Image"). AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif"). AddFilter("All Files", "*.*"). PromptForSingleSelection()
if err != nil { return "", err }
return path, nil}
func (s *FileService) SaveDocument(defaultName string) (string, error) { path, err := s.app.Dialog.SaveFile(). SetTitle("Save Document"). SetFilename(defaultName). AddFilter("PDF Document", "*.pdf"). AddFilter("Text Document", "*.txt"). PromptForSingleSelection()
if err != nil { return "", err }
return path, nil}
func (s *FileService) SelectOutputFolder() (string, error) { path, err := s.app.Dialog.OpenFile(). SetTitle("Select Output Folder"). CanChooseDirectories(true). CanChooseFiles(false). PromptForSingleSelection()
if err != nil { return "", err }
return path, nil}Contoh Dialog Konfirmasi
Section titled “Contoh Dialog Konfirmasi”func (s *Service) DeleteItem(app *application.App, id string) { dialog := app.Dialog.Question(). SetTitle("Confirm Delete"). SetMessage("Are you sure you want to delete this item?")
deleteBtn := dialog.AddButton("Delete") deleteBtn.OnClick(func() { deleteFromDatabase(id) })
cancelBtn := dialog.AddButton("Cancel") // Cancel tidak melakukan apa-apa
dialog.SetDefaultButton(cancelBtn) // Default ke Cancel untuk keamanan dialog.SetCancelButton(cancelBtn) dialog.Show()}Dialog Simpan Perubahan
Section titled “Dialog Simpan Perubahan”func (s *Editor) PromptSaveChanges(app *application.App) { dialog := app.Dialog.Question(). SetTitle("Unsaved Changes"). SetMessage("Do you want to save your changes before closing?")
save := dialog.AddButton("Save") save.OnClick(func() { s.Save() s.Close() })
dontSave := dialog.AddButton("Don't Save") dontSave.OnClick(func() { s.Close() })
cancel := dialog.AddButton("Cancel") // Cancel tidak melakukan apa-apa, dialog ditutup
dialog.SetDefaultButton(save) dialog.SetCancelButton(cancel) dialog.Show()}Pemrosesan Multi-File
Section titled “Pemrosesan Multi-File”func (s *Service) ProcessMultipleFiles(app *application.App) error { // Pilih beberapa file paths, err := app.Dialog.OpenFile(). SetTitle("Select Files to Process"). AddFilter("Images", "*.png;*.jpg"). PromptForMultipleSelection()
if err != nil { return err }
if len(paths) == 0 { app.Dialog.Info(). SetTitle("No Files Selected"). SetMessage("Please select at least one file."). Show() return nil }
// Proses file for _, path := range paths { err := processFile(path) if err != nil { app.Dialog.Error(). SetTitle("Processing Error"). SetMessage(fmt.Sprintf("Failed to process %s: %v", path, err)). Show() continue } }
// Tampilkan penyelesaian app.Dialog.Info(). SetTitle("Complete"). SetMessage(fmt.Sprintf("Successfully processed %d files", len(paths))). Show()
return nil}Penanganan Error dengan Dialog
Section titled “Penanganan Error dengan Dialog”func (s *Service) SaveFile(app *application.App, data []byte) error { // Pilih lokasi simpan path, err := app.Dialog.SaveFile(). SetTitle("Save File"). SetFilename("data.json"). AddFilter("JSON File", "*.json"). PromptForSingleSelection()
if err != nil { // Pengguna membatalkan - bukan error return nil }
// Coba simpan err = os.WriteFile(path, data, 0644) if err != nil { // Tampilkan dialog error app.Dialog.Error(). SetTitle("Save Failed"). SetMessage(fmt.Sprintf("Could not save file: %v", err)). Show() return err }
// Tampilkan sukses app.Dialog.Info(). SetTitle("Success"). SetMessage("File saved successfully!"). Show()
return nil}Default Khusus Platform
Section titled “Default Khusus Platform”import ( "os" "path/filepath" "runtime")
func (s *Service) GetDefaultDirectory() string { homeDir, _ := os.UserHomeDir()
switch runtime.GOOS { case "windows": return filepath.Join(homeDir, "Documents") case "darwin": return filepath.Join(homeDir, "Documents") case "linux": return filepath.Join(homeDir, "Documents") default: return homeDir }}
func (s *Service) OpenWithDefaults(app *application.App) (string, error) { return app.Dialog.OpenFile(). SetTitle("Open File"). SetDirectory(s.GetDefaultDirectory()). AddFilter("All Files", "*.*"). PromptForSingleSelection()}Praktik Terbaik
Section titled “Praktik Terbaik”Lakukan
Section titled “Lakukan”- Gunakan dialog native - Sesuai dengan tampilan dan nuansa platform
- Berikan judul yang jelas - Bantu pengguna memahami tujuan
- Atur filter yang sesuai - Pandu pengguna ke tipe file yang benar
- Tangani pembatalan - Periksa error (pengguna dapat membatalkan)
- Tampilkan konfirmasi untuk aksi destruktif - Gunakan dialog Question
- Berikan umpan balik - Gunakan dialog Info untuk pesan sukses
- Atur default yang masuk akal - Direktori default, nama file, dll.
- Gunakan callback untuk aksi tombol - Tangani respons pengguna dengan benar
Jangan
Section titled “Jangan”- Jangan abaikan error - Pembatalan pengguna mengembalikan error
- Jangan gunakan label tombol ambigu - Spesifik: “Save”/“Cancel”
- Jangan berlebihan menggunakan dialog - Dialog mengganggu alur kerja
- Jangan tampilkan error untuk pembatalan - Itu aksi normal
- Jangan lupa filter file - Bantu pengguna menemukan file yang tepat
- Jangan hardcode path - Gunakan os.UserHomeDir() atau serupa
Jenis Dialog per Platform
Section titled “Jenis Dialog per Platform”- Dialog meluncur turun dari title bar
- Gaya “Sheet” dilampirkan ke window induk
- Tampilan macOS native
Windows
Section titled “Windows”- Dialog Windows standar
- Mengikuti panduan desain Windows
- Tampilan Windows 10/11 modern
- Dialog GTK pada sistem berbasis GTK
- Dialog Qt pada sistem berbasis Qt
- Sesuai dengan desktop environment
Perilaku Dialog Linux
Section titled “Perilaku Dialog Linux”Di Linux, build GTK4 default menggunakan xdg-desktop-portal untuk dialog file, yang menyediakan
integrasi desktop native tetapi berarti beberapa opsi tidak berpengaruh. Jalur GTK3 legacy
(-tags gtk3) mempertahankan kontrol programatik penuh atas opsi ini:
| Opsi | GTK3 (-tags gtk3) | GTK4 (default) | Catatan |
|---|---|---|---|
ShowHiddenFiles() | ✅ Berfungsi | ❌ Tidak berpengaruh | Pengguna mengontrol melalui toggle UI dialog (Ctrl+H atau menu) |
CanCreateDirectories() | ✅ Berfungsi | ❌ Tidak berpengaruh | Selalu diaktifkan di portal |
ResolvesAliases() | ✅ Berfungsi | ❌ Tidak berpengaruh | Portal menangani resolusi symlink |
SetButtonText() | ✅ Berfungsi | ✅ Berfungsi | Teks tombol terima kustom berfungsi |
Mengapa keterbatasan ini ada: Dialog berbasis portal GTK4 mendelegasikan kontrol UI ke desktop environment (GNOME, KDE, dll.). Ini memang disengaja — portal menyediakan UX konsisten di seluruh aplikasi dan menghormati preferensi pengguna.
Pola Umum
Section titled “Pola Umum”Pola “Save As”
Section titled “Pola “Save As””func (s *Service) SaveAs(app *application.App, currentPath string) (string, error) { // Ekstrak nama file dari path saat ini filename := filepath.Base(currentPath)
// Tampilkan dialog simpan path, err := app.Dialog.SaveFile(). SetTitle("Save As"). SetFilename(filename). PromptForSingleSelection()
if err != nil { return "", err }
return path, nil}Pola “Open Recent”
Section titled “Pola “Open Recent””func (s *Service) OpenRecent(app *application.App, recentPath string) error { // Periksa apakah file masih ada if _, err := os.Stat(recentPath); os.IsNotExist(err) { dialog := app.Dialog.Question(). SetTitle("File Not Found"). SetMessage("The file no longer exists. Remove from recent files?")
remove := dialog.AddButton("Remove") remove.OnClick(func() { s.removeFromRecent(recentPath) })
cancel := dialog.AddButton("Cancel") dialog.SetCancelButton(cancel) dialog.Show()
return err }
return s.openFile(recentPath)}