mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
docs: Update dialogs documentation to match actual v3 API (#4793)
* All the documentation files have been updated. Here's a summary of the changes I made:
## Summary of Documentation Updates
### Key API Corrections Made:
1. **Dialog Creation**:
- Changed `app.InfoDialog()` → `application.InfoDialog()` (package-level functions)
- Also documented `app.Dialog.Info()` via DialogManager
2. **Question Dialog Buttons**:
- Removed non-existent `SetButtons("Save", "Don't Save", "Cancel")` method
- Now uses `AddButton("label")` which returns a `*Button`
- Button callbacks via `button.OnClick(func() { ... })`
3. **Default/Cancel Buttons**:
- Changed `SetDefaultButton("Cancel")` (string) → `SetDefaultButton(cancelBtn)` (`*Button`)
- Changed `SetCancelButton("Cancel")` (string) → `SetCancelButton(cancelBtn)` (`*Button`)
- Also documented fluent `SetAsDefault()` and `SetAsCancel()` methods on Button
4. **File Dialog Filters**:
- Changed `SetFilters([]application.FileFilter{...})` → `AddFilter("Display Name", "*.ext;*.ext2")`
5. **Save Dialog Filename**:
- Changed `SetDefaultFilename()` → `SetFilename()`
6. **Folder Selection**:
- Removed non-existent `app.SelectFolderDialog()`
- Now uses `application.OpenFileDialog().CanChooseDirectories(true).CanChooseFiles(false)`
7. **Show() Return Value**:
- Removed incorrect `result, err := dialog.Show()` pattern
- `Show()` returns nothing - responses are handled via button callbacks
### Files Modified:
- `docs/src/content/docs/features/dialogs/message.mdx` - Complete rewrite of question dialog examples
- `docs/src/content/docs/features/dialogs/overview.mdx` - Updated all code examples
- `docs/src/content/docs/features/dialogs/file.mdx` - Updated file dialog examples
- `v3/UNRELEASED_CHANGELOG.md` - Added changelog entry
* All changes are complete. Here's a summary of what was updated:
## Summary
I've updated the Wails v3 dialogs documentation to match the actual API. The documentation now consistently uses:
### DialogManager Pattern (Recommended)
- `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`
- `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()`
This is consistent with other runtime features like `app.Window`, `app.Event`, etc.
### Key API Corrections
1. **Dialog Creation**: Both `app.Dialog.*()` (DialogManager) and `application.*Dialog()` (package-level) are documented
2. **Question Dialog Buttons**: Use `AddButton("label")` which returns `*Button`, then `button.OnClick(callback)`
3. **Default/Cancel Buttons**: `SetDefaultButton(button)` and `SetCancelButton(button)` take `*Button` pointers
4. **File Filters**: Use `AddFilter("Display Name", "*.ext")` instead of `SetFilters()`
5. **Save Dialog Filename**: Use `SetFilename()` instead of `SetDefaultFilename()`
6. **Folder Selection**: Use `app.Dialog.OpenFile().CanChooseDirectories(true).CanChooseFiles(false)`
### Files Modified
- `docs/src/content/docs/features/dialogs/overview.mdx`
- `docs/src/content/docs/features/dialogs/message.mdx`
- `docs/src/content/docs/features/dialogs/file.mdx`
- `v3/UNRELEASED_CHANGELOG.md`
* Audit complete! All documentation files now consistently use `app.Dialog.*` for all code examples. Here's the summary:
## Audit Complete
All dialog documentation has been updated to consistently use the `app.Dialog.*` pattern:
### Changes Made:
**message.mdx:**
- All examples now use `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`
- Function signatures updated to accept `app *application.App` parameter
- Nested dialog calls within callbacks also updated
**file.mdx:**
- All examples now use `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()`
- Function signatures updated to accept `app *application.App` parameter
- All error/info dialogs within file operations also updated
**overview.mdx:**
- Already consistent from earlier edits
### Documentation Structure:
Each file now properly documents both approaches in a dedicated section:
```go
// Via DialogManager (recommended when you have an app instance):
app.Dialog.Info()
app.Dialog.OpenFile()
// Package-level functions (useful in callbacks or when app isn't in scope):
application.InfoDialog()
application.OpenFileDialog()
```
But all code examples use the `app.Dialog.*` pattern for consistency with other runtime features like `app.Window`, `app.Event`, etc.
* docs: Fix reference/dialogs.mdx and reference/application.mdx API documentation
Updated docs to match actual Wails v3 Dialogs API:
- reference/dialogs.mdx: Complete rewrite with correct API
- Use `app.Dialog.OpenFile()` and `app.Dialog.SaveFile()` instead of `app.OpenFileDialog()`
- Use `AddFilter("name", "pattern")` instead of `SetFilters([]FileFilter{...})`
- Use `SetFilename()` instead of `SetDefaultFilename()`
- Use `SetDirectory()` instead of `SetDefaultDirectory()`
- Remove non-existent `SelectFolderDialog()` - use `OpenFile().CanChooseDirectories(true).CanChooseFiles(false)`
- Use `AddButton()` with callbacks instead of `SetButtons()`
- Use `SetDefaultButton(*Button)` instead of `SetDefaultButton(int)`
- Document that `Show()` returns nothing, use callbacks
- reference/application.mdx: Fix Dialog Methods section
- Use `app.Dialog.*` manager pattern
- Show correct Question dialog with button callbacks
- Fix file dialog examples with `AddFilter()`
- Remove `SelectFolderDialog()` reference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: Remove package-level dialog function references
Remove all references to package-level dialog functions
(application.InfoDialog(), application.OpenFileDialog(), etc.)
from documentation. Only the app.Dialog manager pattern
should be used.
Updated files:
- reference/dialogs.mdx
- features/dialogs/overview.mdx
- features/dialogs/message.mdx
- features/dialogs/file.mdx
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: Remove package-level dialog functions in favor of app.Dialog manager
BREAKING CHANGE: Remove package-level dialog functions. Use app.Dialog manager instead.
Removed functions:
- application.InfoDialog()
- application.QuestionDialog()
- application.WarningDialog()
- application.ErrorDialog()
- application.OpenFileDialog()
- application.SaveFileDialog()
Use the Dialog manager pattern instead:
- app.Dialog.Info()
- app.Dialog.Question()
- app.Dialog.Warning()
- app.Dialog.Error()
- app.Dialog.OpenFile()
- app.Dialog.SaveFile()
This aligns dialogs with other runtime managers like app.Window and app.Event.
Updated files:
- v3/pkg/application/application.go - Remove exported dialog functions
- v3/pkg/application/dialog_manager.go - Use internal newMessageDialog/newOpenFileDialog
- v3/pkg/application/messageprocessor_dialog.go - Use internal dialog constructors
- v3/examples/* - Update all examples to use app.Dialog pattern
- v3/internal/commands/appimage_testfiles/main.go - Update test file
- v3/UNRELEASED_CHANGELOG.md - Document breaking change
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: Use application.Get() in dialogs-basic example and correct filter docs
- Update dialogs-basic helper functions to use application.Get() instead
of passing app through function parameters
- Fix incorrect documentation claiming space/comma delimiters work for
filter patterns (only semicolons are supported)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f3af37be72
commit
84b9021ea9
20 changed files with 1109 additions and 1044 deletions
|
|
@ -10,20 +10,28 @@ import { Card, CardGrid } from "@astrojs/starlight/components";
|
|||
## File dialogs
|
||||
|
||||
Wails provides **native file dialogs** with platform-appropriate appearance for opening files, saving files, and selecting folders. Simple API with file type filtering, multiple selection support, and default locations.
|
||||
|
||||
## Creating File Dialogs
|
||||
|
||||
File dialogs are accessed through the `app.Dialog` manager:
|
||||
|
||||
```go
|
||||
app.Dialog.OpenFile()
|
||||
app.Dialog.SaveFile()
|
||||
```
|
||||
|
||||
## Open File dialog
|
||||
|
||||
Select files to open:
|
||||
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.gif"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.gif").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -39,15 +47,13 @@ openFile(path)
|
|||
### Single File Selection
|
||||
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Open Document").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Text Files", Pattern: "*.txt"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
if err != nil || path == "" {
|
||||
// User cancelled or error occurred
|
||||
return
|
||||
}
|
||||
|
|
@ -59,11 +65,9 @@ data, _ := os.ReadFile(path)
|
|||
### Multiple File Selection
|
||||
|
||||
```go
|
||||
paths, err := app.OpenFileDialog().
|
||||
paths, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Images").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.jpeg;*.gif"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif").
|
||||
PromptForMultipleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -79,7 +83,7 @@ for _, path := range paths {
|
|||
### With Default Directory
|
||||
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Open File").
|
||||
SetDirectory("/Users/me/Documents").
|
||||
PromptForSingleSelection()
|
||||
|
|
@ -90,16 +94,13 @@ path, err := app.OpenFileDialog().
|
|||
Choose where to save:
|
||||
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save Document").
|
||||
SetDefaultFilename("document.txt").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Text Files", Pattern: "*.txt"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("document.txt").
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -115,48 +116,48 @@ saveFile(path, data)
|
|||
### With Default Filename
|
||||
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Export Data").
|
||||
SetDefaultFilename("export.csv").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "CSV Files", Pattern: "*.csv"},
|
||||
}).
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("export.csv").
|
||||
AddFilter("CSV Files", "*.csv").
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
### With Default Directory
|
||||
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save File").
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetDirectory("/Users/me/Documents").
|
||||
SetDefaultFilename("untitled.txt").
|
||||
SetFilename("untitled.txt").
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
### Overwrite Confirmation
|
||||
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save File").
|
||||
SetDefaultFilename("document.txt").
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("document.txt").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if file exists
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Overwrite").
|
||||
SetMessage("File already exists. Overwrite?").
|
||||
SetButtons("Overwrite", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Overwrite" {
|
||||
return
|
||||
}
|
||||
SetMessage("File already exists. Overwrite?")
|
||||
|
||||
overwriteBtn := dialog.AddButton("Overwrite")
|
||||
overwriteBtn.OnClick(func() {
|
||||
saveFile(path, data)
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
return
|
||||
}
|
||||
|
||||
saveFile(path, data)
|
||||
|
|
@ -164,14 +165,16 @@ saveFile(path, data)
|
|||
|
||||
## Select Folder dialog
|
||||
|
||||
Choose a directory:
|
||||
Choose a directory using the open file dialog with directory selection enabled:
|
||||
|
||||
```go
|
||||
path, err := app.SelectFolderDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Output Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -187,66 +190,45 @@ exportToFolder(path)
|
|||
### With Default Directory
|
||||
|
||||
```go
|
||||
path, err := app.SelectFolderDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Folder").
|
||||
SetDirectory("/Users/me/Documents").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
## File Filters
|
||||
|
||||
Use the `AddFilter()` method to add file type filters to dialogs. Each call adds a new filter option.
|
||||
|
||||
### Basic Filters
|
||||
|
||||
```go
|
||||
filters := []application.FileFilter{
|
||||
{DisplayName: "Text Files", Pattern: "*.txt"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}
|
||||
|
||||
path, _ := app.OpenFileDialog().
|
||||
SetFilters(filters).
|
||||
path, _ := app.Dialog.OpenFile().
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
### Multiple Extensions
|
||||
|
||||
Use semicolons to specify multiple extensions in a single filter:
|
||||
|
||||
```go
|
||||
filters := []application.FileFilter{
|
||||
{
|
||||
DisplayName: "Images",
|
||||
Pattern: "*.png;*.jpg;*.jpeg;*.gif;*.bmp",
|
||||
},
|
||||
{
|
||||
DisplayName: "Documents",
|
||||
Pattern: "*.txt;*.doc;*.docx;*.pdf",
|
||||
},
|
||||
{
|
||||
DisplayName: "All Files",
|
||||
Pattern: "*.*",
|
||||
},
|
||||
}
|
||||
dialog := app.Dialog.OpenFile().
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif;*.bmp").
|
||||
AddFilter("Documents", "*.txt;*.doc;*.docx;*.pdf").
|
||||
AddFilter("All Files", "*.*")
|
||||
```
|
||||
|
||||
### Platform-Specific Patterns
|
||||
### Pattern Format
|
||||
|
||||
**Windows:**
|
||||
```go
|
||||
// Semicolon-separated
|
||||
Pattern: "*.png;*.jpg;*.gif"
|
||||
```
|
||||
Use **semicolons** to separate multiple extensions in a single filter:
|
||||
|
||||
**macOS/Linux:**
|
||||
```go
|
||||
// Space or comma-separated (both work)
|
||||
Pattern: "*.png *.jpg *.gif"
|
||||
// or
|
||||
Pattern: "*.png,*.jpg,*.gif"
|
||||
```
|
||||
|
||||
**Cross-platform (recommended):**
|
||||
```go
|
||||
// Use semicolons (works on all platforms)
|
||||
Pattern: "*.png;*.jpg;*.gif"
|
||||
// Multiple extensions separated by semicolons
|
||||
AddFilter("Images", "*.png;*.jpg;*.gif")
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
|
@ -254,41 +236,40 @@ Pattern: "*.png;*.jpg;*.gif"
|
|||
### Open Image File
|
||||
|
||||
```go
|
||||
func openImage() (image.Image, error) {
|
||||
path, err := app.OpenFileDialog().
|
||||
func openImage(app *application.App) (image.Image, error) {
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{
|
||||
DisplayName: "Images",
|
||||
Pattern: "*.png;*.jpg;*.jpeg;*.gif;*.bmp",
|
||||
},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif;*.bmp").
|
||||
PromptForSingleSelection()
|
||||
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
if path == "" {
|
||||
return nil, errors.New("no file selected")
|
||||
}
|
||||
|
||||
// Open and decode image
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Open Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Invalid Image").
|
||||
SetMessage("Could not decode image file.").
|
||||
Show()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return img, nil
|
||||
}
|
||||
```
|
||||
|
|
@ -296,214 +277,216 @@ func openImage() (image.Image, error) {
|
|||
### Save Document with Validation
|
||||
|
||||
```go
|
||||
func saveDocument(content string) error {
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save Document").
|
||||
SetDefaultFilename("document.txt").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Text Files", Pattern: "*.txt"},
|
||||
{DisplayName: "Markdown Files", Pattern: "*.md"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
func saveDocument(app *application.App, content string) {
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("document.txt").
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AddFilter("Markdown Files", "*.md").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Validate extension
|
||||
ext := filepath.Ext(path)
|
||||
if ext != ".txt" && ext != ".md" {
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Extension").
|
||||
SetMessage(fmt.Sprintf("Save as %s file?", ext)).
|
||||
SetButtons("Save", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Save" {
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
SetMessage(fmt.Sprintf("Save as %s file?", ext))
|
||||
|
||||
saveBtn := dialog.AddButton("Save")
|
||||
saveBtn.OnClick(func() {
|
||||
doSave(app, path, content)
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
return
|
||||
}
|
||||
|
||||
// Save file
|
||||
|
||||
doSave(app, path, content)
|
||||
}
|
||||
|
||||
func doSave(app *application.App, path, content string) {
|
||||
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Save Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
|
||||
app.Dialog.Info().
|
||||
SetTitle("Saved").
|
||||
SetMessage("Document saved successfully!").
|
||||
Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### Batch File Processing
|
||||
|
||||
```go
|
||||
func processMultipleFiles() {
|
||||
paths, err := app.OpenFileDialog().
|
||||
func processMultipleFiles(app *application.App) {
|
||||
paths, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Files to Process").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForMultipleSelection()
|
||||
|
||||
|
||||
if err != nil || len(paths) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Confirm processing
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Processing").
|
||||
SetMessage(fmt.Sprintf("Process %d file(s)?", len(paths))).
|
||||
SetButtons("Process", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Process" {
|
||||
return
|
||||
}
|
||||
|
||||
// Process files
|
||||
var errors []error
|
||||
for i, path := range paths {
|
||||
if err := processFile(path); err != nil {
|
||||
errors = append(errors, err)
|
||||
SetMessage(fmt.Sprintf("Process %d file(s)?", len(paths)))
|
||||
|
||||
processBtn := dialog.AddButton("Process")
|
||||
processBtn.OnClick(func() {
|
||||
// Process files
|
||||
var errs []error
|
||||
for i, path := range paths {
|
||||
if err := processFile(path); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
// Update progress
|
||||
// app.Event.Emit("progress", map[string]interface{}{
|
||||
// "current": i + 1,
|
||||
// "total": len(paths),
|
||||
// })
|
||||
_ = i // suppress unused variable warning in example
|
||||
}
|
||||
|
||||
// Update progress
|
||||
app.EmitEvent("progress", map[string]interface{}{
|
||||
"current": i + 1,
|
||||
"total": len(paths),
|
||||
})
|
||||
}
|
||||
|
||||
// Show results
|
||||
if len(errors) > 0 {
|
||||
app.WarningDialog().
|
||||
SetTitle("Processing Complete").
|
||||
SetMessage(fmt.Sprintf("Processed %d files with %d errors.",
|
||||
len(paths), len(errors))).
|
||||
Show()
|
||||
} else {
|
||||
app.InfoDialog().
|
||||
SetTitle("Success").
|
||||
SetMessage(fmt.Sprintf("Processed %d files successfully!", len(paths))).
|
||||
Show()
|
||||
}
|
||||
|
||||
// Show results
|
||||
if len(errs) > 0 {
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Processing Complete").
|
||||
SetMessage(fmt.Sprintf("Processed %d files with %d errors.",
|
||||
len(paths), len(errs))).
|
||||
Show()
|
||||
} else {
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage(fmt.Sprintf("Processed %d files successfully!", len(paths))).
|
||||
Show()
|
||||
}
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Export with Folder Selection
|
||||
|
||||
```go
|
||||
func exportData(data []byte) error {
|
||||
func exportData(app *application.App, data []byte) {
|
||||
// Select output folder
|
||||
folder, err := app.SelectFolderDialog().
|
||||
folder, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Export Folder").
|
||||
SetDirectory(getDefaultExportFolder()).
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if err != nil || folder == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Generate filename
|
||||
filename := fmt.Sprintf("export_%s.csv",
|
||||
filename := fmt.Sprintf("export_%s.csv",
|
||||
time.Now().Format("2006-01-02_15-04-05"))
|
||||
path := filepath.Join(folder, filename)
|
||||
|
||||
|
||||
// Save file
|
||||
if err := os.WriteFile(path, data, 0644); err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Export Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Show success with option to open folder
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Export Complete").
|
||||
SetMessage(fmt.Sprintf("Exported to %s", filename)).
|
||||
SetButtons("Open Folder", "OK").
|
||||
Show()
|
||||
|
||||
if result == "Open Folder" {
|
||||
SetMessage(fmt.Sprintf("Exported to %s", filename))
|
||||
|
||||
openBtn := dialog.AddButton("Open Folder")
|
||||
openBtn.OnClick(func() {
|
||||
openFolder(folder)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
dialog.AddButton("OK")
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Import with Validation
|
||||
|
||||
```go
|
||||
func importConfiguration() error {
|
||||
path, err := app.OpenFileDialog().
|
||||
func importConfiguration(app *application.App) {
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Import Configuration").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "JSON Files", Pattern: "*.json"},
|
||||
{DisplayName: "YAML Files", Pattern: "*.yaml;*.yml"},
|
||||
}).
|
||||
AddFilter("JSON Files", "*.json").
|
||||
AddFilter("YAML Files", "*.yaml;*.yml").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Read file
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Read Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Validate configuration
|
||||
config, err := parseConfig(data)
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Invalid Configuration").
|
||||
SetMessage("File is not a valid configuration.").
|
||||
Show()
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Confirm import
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Import").
|
||||
SetMessage("Import this configuration?").
|
||||
SetButtons("Import", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Import" {
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
|
||||
// Apply configuration
|
||||
if err := applyConfig(config); err != nil {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Import Failed").
|
||||
SetMessage(err.Error()).
|
||||
SetMessage("Import this configuration?")
|
||||
|
||||
importBtn := dialog.AddButton("Import")
|
||||
importBtn.OnClick(func() {
|
||||
// Apply configuration
|
||||
if err := applyConfig(config); err != nil {
|
||||
app.Dialog.Error().
|
||||
SetTitle("Import Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("Configuration imported successfully!").
|
||||
Show()
|
||||
return err
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
SetTitle("Success").
|
||||
SetMessage("Configuration imported successfully!").
|
||||
Show()
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,26 @@ import { Card, CardGrid } from "@astrojs/starlight/components";
|
|||
## Message dialogs
|
||||
|
||||
Wails provides **native message dialogs** with platform-appropriate appearance: info, warning, error, and question dialogs with customisable titles, messages, and buttons. Simple API, native behaviour, accessible by default.
|
||||
|
||||
## Creating Dialogs
|
||||
|
||||
Message dialogs are accessed through the `app.Dialog` manager:
|
||||
|
||||
```go
|
||||
app.Dialog.Info()
|
||||
app.Dialog.Question()
|
||||
app.Dialog.Warning()
|
||||
app.Dialog.Error()
|
||||
```
|
||||
|
||||
All methods return a `*MessageDialog` that can be configured using method chaining.
|
||||
|
||||
## Information dialog
|
||||
|
||||
Display informational messages:
|
||||
|
||||
```go
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("File saved successfully!").
|
||||
Show()
|
||||
|
|
@ -30,16 +44,16 @@ app.InfoDialog().
|
|||
**Example - Save confirmation:**
|
||||
|
||||
```go
|
||||
func saveFile(path string, data []byte) error {
|
||||
func saveFile(app *application.App, path string, data []byte) error {
|
||||
if err := os.WriteFile(path, data, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
|
||||
app.Dialog.Info().
|
||||
SetTitle("File Saved").
|
||||
SetMessage(fmt.Sprintf("Saved to %s", filepath.Base(path))).
|
||||
Show()
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
|
@ -49,7 +63,7 @@ func saveFile(path string, data []byte) error {
|
|||
Show warnings:
|
||||
|
||||
```go
|
||||
app.WarningDialog().
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Warning").
|
||||
SetMessage("This action cannot be undone.").
|
||||
Show()
|
||||
|
|
@ -64,11 +78,11 @@ app.WarningDialog().
|
|||
**Example - Disk space warning:**
|
||||
|
||||
```go
|
||||
func checkDiskSpace() {
|
||||
func checkDiskSpace(app *application.App) {
|
||||
available := getDiskSpace()
|
||||
|
||||
|
||||
if available < 100*1024*1024 { // Less than 100MB
|
||||
app.WarningDialog().
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Low Disk Space").
|
||||
SetMessage(fmt.Sprintf("Only %d MB available.", available/(1024*1024))).
|
||||
Show()
|
||||
|
|
@ -81,7 +95,7 @@ func checkDiskSpace() {
|
|||
Display errors:
|
||||
|
||||
```go
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Error").
|
||||
SetMessage("Failed to connect to server.").
|
||||
Show()
|
||||
|
|
@ -96,41 +110,48 @@ app.ErrorDialog().
|
|||
**Example - Network error:**
|
||||
|
||||
```go
|
||||
func fetchData(url string) ([]byte, error) {
|
||||
func fetchData(app *application.App, url string) ([]byte, error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Network Error").
|
||||
SetMessage(fmt.Sprintf("Failed to connect: %v", err)).
|
||||
Show()
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
```
|
||||
|
||||
## Question dialog
|
||||
|
||||
Ask users questions:
|
||||
Ask users questions and handle responses via button callbacks:
|
||||
|
||||
```go
|
||||
result, err := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm").
|
||||
SetMessage("Save changes before closing?").
|
||||
SetButtons("Save", "Don't Save", "Cancel").
|
||||
SetDefaultButton("Save").
|
||||
Show()
|
||||
SetMessage("Save changes before closing?")
|
||||
|
||||
switch result {
|
||||
case "Save":
|
||||
save := dialog.AddButton("Save")
|
||||
save.OnClick(func() {
|
||||
saveChanges()
|
||||
case "Don't Save":
|
||||
})
|
||||
|
||||
dontSave := dialog.AddButton("Don't Save")
|
||||
dontSave.OnClick(func() {
|
||||
// Continue without saving
|
||||
case "Cancel":
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
cancel.OnClick(func() {
|
||||
// Don't close
|
||||
}
|
||||
})
|
||||
|
||||
dialog.SetDefaultButton(save)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
|
|
@ -142,32 +163,34 @@ case "Cancel":
|
|||
**Example - Unsaved changes:**
|
||||
|
||||
```go
|
||||
func closeDocument() bool {
|
||||
func closeDocument(app *application.App) {
|
||||
if !hasUnsavedChanges() {
|
||||
return true
|
||||
doClose()
|
||||
return
|
||||
}
|
||||
|
||||
result, err := app.QuestionDialog().
|
||||
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Unsaved Changes").
|
||||
SetMessage("Do you want to save your changes?").
|
||||
SetButtons("Save", "Don't Save", "Cancel").
|
||||
SetDefaultButton("Save").
|
||||
Show()
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
switch result {
|
||||
case "Save":
|
||||
return saveDocument()
|
||||
case "Don't Save":
|
||||
return true
|
||||
case "Cancel":
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
SetMessage("Do you want to save your changes?")
|
||||
|
||||
save := dialog.AddButton("Save")
|
||||
save.OnClick(func() {
|
||||
if saveDocument() {
|
||||
doClose()
|
||||
}
|
||||
})
|
||||
|
||||
dontSave := dialog.AddButton("Don't Save")
|
||||
dontSave.OnClick(func() {
|
||||
doClose()
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
// Cancel button has no callback - just closes the dialog
|
||||
|
||||
dialog.SetDefaultButton(save)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -176,7 +199,7 @@ func closeDocument() bool {
|
|||
### Title and Message
|
||||
|
||||
```go
|
||||
dialog := app.InfoDialog().
|
||||
dialog := app.Dialog.Info().
|
||||
SetTitle("Operation Complete").
|
||||
SetMessage("All files have been processed successfully.")
|
||||
```
|
||||
|
|
@ -190,30 +213,85 @@ dialog := app.InfoDialog().
|
|||
|
||||
**Single button (Info/Warning/Error):**
|
||||
|
||||
Info, warning, and error dialogs display a default "OK" button:
|
||||
|
||||
```go
|
||||
// Default "OK" button
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetMessage("Done!").
|
||||
Show()
|
||||
```
|
||||
|
||||
**Multiple buttons (Question):**
|
||||
You can also add custom buttons:
|
||||
|
||||
```go
|
||||
result, _ := app.QuestionDialog().
|
||||
SetMessage("Choose an action").
|
||||
SetButtons("Option 1", "Option 2", "Option 3").
|
||||
Show()
|
||||
dialog := app.Dialog.Info().
|
||||
SetMessage("Done!")
|
||||
ok := dialog.AddButton("Got it!")
|
||||
dialog.SetDefaultButton(ok)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Default button:**
|
||||
**Multiple buttons (Question):**
|
||||
|
||||
Use `AddButton()` to add buttons, which returns a `*Button` you can configure:
|
||||
|
||||
```go
|
||||
app.QuestionDialog().
|
||||
SetMessage("Delete file?").
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton("Cancel"). // Safe option
|
||||
Show()
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Choose an action")
|
||||
|
||||
option1 := dialog.AddButton("Option 1")
|
||||
option1.OnClick(func() {
|
||||
handleOption1()
|
||||
})
|
||||
|
||||
option2 := dialog.AddButton("Option 2")
|
||||
option2.OnClick(func() {
|
||||
handleOption2()
|
||||
})
|
||||
|
||||
option3 := dialog.AddButton("Option 3")
|
||||
option3.OnClick(func() {
|
||||
handleOption3()
|
||||
})
|
||||
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Default and Cancel buttons:**
|
||||
|
||||
Use `SetDefaultButton()` to specify which button is highlighted and triggered by Enter.
|
||||
Use `SetCancelButton()` to specify which button is triggered by Escape.
|
||||
|
||||
```go
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Delete file?")
|
||||
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
performDelete()
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
// No callback needed - just dismisses dialog
|
||||
|
||||
dialog.SetDefaultButton(cancelBtn) // Safe option as default
|
||||
dialog.SetCancelButton(cancelBtn) // Escape triggers Cancel
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
You can also use the fluent `SetAsDefault()` and `SetAsCancel()` methods on buttons:
|
||||
|
||||
```go
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Delete file?")
|
||||
|
||||
dialog.AddButton("Delete").OnClick(func() {
|
||||
performDelete()
|
||||
})
|
||||
|
||||
dialog.AddButton("Cancel").SetAsDefault().SetAsCancel()
|
||||
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Best practices:**
|
||||
|
|
@ -222,16 +300,29 @@ app.QuestionDialog().
|
|||
- **Safe default:** Non-destructive action
|
||||
- **Order matters:** Most likely action first (except Cancel)
|
||||
|
||||
### Custom Icon
|
||||
|
||||
Set a custom icon for the dialog:
|
||||
|
||||
```go
|
||||
app.Dialog.Info().
|
||||
SetTitle("Custom Icon Example").
|
||||
SetMessage("Using a custom icon").
|
||||
SetIcon(myIconBytes).
|
||||
Show()
|
||||
```
|
||||
|
||||
### Window Attachment
|
||||
|
||||
Attach to specific window:
|
||||
|
||||
```go
|
||||
dialog := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Window-specific question").
|
||||
AttachToWindow(window)
|
||||
|
||||
result, _ := dialog.Show()
|
||||
dialog.AddButton("OK")
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
|
@ -244,163 +335,111 @@ result, _ := dialog.Show()
|
|||
### Confirm Destructive Action
|
||||
|
||||
```go
|
||||
func deleteFiles(paths []string) error {
|
||||
func deleteFiles(app *application.App, paths []string) {
|
||||
// Confirm deletion
|
||||
message := fmt.Sprintf("Delete %d file(s)?", len(paths))
|
||||
if len(paths) == 1 {
|
||||
message = fmt.Sprintf("Delete %s?", filepath.Base(paths[0]))
|
||||
}
|
||||
|
||||
result, err := app.QuestionDialog().
|
||||
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Delete").
|
||||
SetMessage(message).
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton("Cancel").
|
||||
Show()
|
||||
|
||||
if err != nil || result != "Delete" {
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
|
||||
// Perform deletion
|
||||
var errors []error
|
||||
for _, path := range paths {
|
||||
if err := os.Remove(path); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Show result
|
||||
if len(errors) > 0 {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Delete Failed").
|
||||
SetMessage(fmt.Sprintf("Failed to delete %d file(s)", len(errors))).
|
||||
Show()
|
||||
return fmt.Errorf("%d errors", len(errors))
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
SetTitle("Delete Complete").
|
||||
SetMessage(fmt.Sprintf("Deleted %d file(s)", len(paths))).
|
||||
Show()
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
SetMessage(message)
|
||||
|
||||
### Error Handling with Retry
|
||||
|
||||
```go
|
||||
func connectToServer(url string) error {
|
||||
for attempts := 0; attempts < 3; attempts++ {
|
||||
if err := tryConnect(url); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if attempts < 2 {
|
||||
result, _ := app.QuestionDialog().
|
||||
SetTitle("Connection Failed").
|
||||
SetMessage("Failed to connect. Retry?").
|
||||
SetButtons("Retry", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Retry" {
|
||||
return errors.New("cancelled")
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
// Perform deletion
|
||||
var errs []error
|
||||
for _, path := range paths {
|
||||
if err := os.Remove(path); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.ErrorDialog().
|
||||
SetTitle("Connection Failed").
|
||||
SetMessage("Could not connect after 3 attempts.").
|
||||
Show()
|
||||
|
||||
return errors.New("connection failed")
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-Step Workflow
|
||||
|
||||
```go
|
||||
func exportAndEmail() {
|
||||
// Step 1: Confirm export
|
||||
result, _ := app.QuestionDialog().
|
||||
SetTitle("Export and Email").
|
||||
SetMessage("Export data and send via email?").
|
||||
SetButtons("Continue", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Continue" {
|
||||
return
|
||||
}
|
||||
|
||||
// Step 2: Export data
|
||||
data, err := exportData()
|
||||
if err != nil {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Export Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
// Step 3: Send email
|
||||
if err := sendEmail(data); err != nil {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Email Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
// Step 4: Success
|
||||
app.InfoDialog().
|
||||
SetTitle("Success").
|
||||
SetMessage("Data exported and emailed successfully!").
|
||||
Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Validation with Feedback
|
||||
|
||||
```go
|
||||
func validateAndSave(data string) error {
|
||||
// Validate
|
||||
if err := validate(data); err != nil {
|
||||
app.WarningDialog().
|
||||
SetTitle("Validation Warning").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
|
||||
result, _ := app.QuestionDialog().
|
||||
SetMessage("Save anyway?").
|
||||
SetButtons("Save", "Cancel").
|
||||
SetDefaultButton("Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Save" {
|
||||
return errors.New("cancelled")
|
||||
// Show result
|
||||
if len(errs) > 0 {
|
||||
app.Dialog.Error().
|
||||
SetTitle("Delete Failed").
|
||||
SetMessage(fmt.Sprintf("Failed to delete %d file(s)", len(errs))).
|
||||
Show()
|
||||
} else {
|
||||
app.Dialog.Info().
|
||||
SetTitle("Delete Complete").
|
||||
SetMessage(fmt.Sprintf("Deleted %d file(s)", len(paths))).
|
||||
Show()
|
||||
}
|
||||
}
|
||||
|
||||
// Save
|
||||
if err := save(data); err != nil {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Save Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return err
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
SetTitle("Saved").
|
||||
SetMessage("Data saved successfully!").
|
||||
Show()
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Quit Confirmation
|
||||
|
||||
```go
|
||||
func confirmQuit(app *application.App) {
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Quit").
|
||||
SetMessage("You have unsaved work. Are you sure you want to quit?")
|
||||
|
||||
yes := dialog.AddButton("Yes")
|
||||
yes.OnClick(func() {
|
||||
app.Quit()
|
||||
})
|
||||
|
||||
no := dialog.AddButton("No")
|
||||
dialog.SetDefaultButton(no)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Update Dialog with Download Option
|
||||
|
||||
```go
|
||||
func showUpdateDialog(app *application.App) {
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Update").
|
||||
SetMessage("A new version is available. The cancel button is selected when pressing escape.")
|
||||
|
||||
download := dialog.AddButton("📥 Download")
|
||||
download.OnClick(func() {
|
||||
app.Dialog.Info().SetMessage("Downloading...").Show()
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
|
||||
dialog.SetDefaultButton(download)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Icon Question
|
||||
|
||||
```go
|
||||
func showCustomIconQuestion(app *application.App, iconBytes []byte) {
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Custom Icon Example").
|
||||
SetMessage("Using a custom icon").
|
||||
SetIcon(iconBytes)
|
||||
|
||||
likeIt := dialog.AddButton("I like it!")
|
||||
likeIt.OnClick(func() {
|
||||
app.Dialog.Info().SetMessage("Thanks!").Show()
|
||||
})
|
||||
|
||||
notKeen := dialog.AddButton("Not so keen...")
|
||||
notKeen.OnClick(func() {
|
||||
app.Dialog.Info().SetMessage("Too bad!").Show()
|
||||
})
|
||||
|
||||
dialog.SetDefaultButton(likeIt)
|
||||
dialog.Show()
|
||||
}
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✅ Do
|
||||
|
|
|
|||
|
|
@ -15,33 +15,48 @@ Wails provides **native system dialogs** that work across all platforms: message
|
|||
|
||||
```go
|
||||
// Information dialog
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("File saved successfully!").
|
||||
Show()
|
||||
|
||||
// Question dialog
|
||||
result, _ := app.QuestionDialog().
|
||||
// Question dialog with button callbacks
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm").
|
||||
SetMessage("Delete this file?").
|
||||
SetButtons("Delete", "Cancel").
|
||||
Show()
|
||||
SetMessage("Delete this file?")
|
||||
|
||||
if result == "Delete" {
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
deleteFile()
|
||||
}
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
|
||||
// File open dialog
|
||||
path, _ := app.OpenFileDialog().
|
||||
path, _ := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
**That's it!** Native dialogs with minimal code.
|
||||
|
||||
## Accessing Dialogs
|
||||
|
||||
Dialogs are accessed through the `app.Dialog` manager:
|
||||
|
||||
```go
|
||||
app.Dialog.Info()
|
||||
app.Dialog.Question()
|
||||
app.Dialog.Warning()
|
||||
app.Dialog.Error()
|
||||
app.Dialog.OpenFile()
|
||||
app.Dialog.SaveFile()
|
||||
```
|
||||
|
||||
## dialog Types
|
||||
|
||||
### Information dialog
|
||||
|
|
@ -49,7 +64,7 @@ path, _ := app.OpenFileDialog().
|
|||
Display simple messages:
|
||||
|
||||
```go
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Welcome").
|
||||
SetMessage("Welcome to our application!").
|
||||
Show()
|
||||
|
|
@ -65,7 +80,7 @@ app.InfoDialog().
|
|||
Show warnings:
|
||||
|
||||
```go
|
||||
app.WarningDialog().
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Warning").
|
||||
SetMessage("This action cannot be undone.").
|
||||
Show()
|
||||
|
|
@ -81,7 +96,7 @@ app.WarningDialog().
|
|||
Display errors:
|
||||
|
||||
```go
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Error").
|
||||
SetMessage("Failed to save file: " + err.Error()).
|
||||
Show()
|
||||
|
|
@ -94,19 +109,22 @@ app.ErrorDialog().
|
|||
|
||||
### Question dialog
|
||||
|
||||
Ask users questions:
|
||||
Ask users questions and handle responses via button callbacks:
|
||||
|
||||
```go
|
||||
result, err := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Delete").
|
||||
SetMessage("Are you sure you want to delete this file?").
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton("Cancel").
|
||||
Show()
|
||||
SetMessage("Are you sure you want to delete this file?")
|
||||
|
||||
if result == "Delete" {
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
deleteFile()
|
||||
}
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
|
|
@ -121,15 +139,13 @@ if result == "Delete" {
|
|||
Select files to open:
|
||||
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.gif"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.gif").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err == nil {
|
||||
if err == nil && path != "" {
|
||||
openFile(path)
|
||||
}
|
||||
```
|
||||
|
|
@ -137,15 +153,15 @@ if err == nil {
|
|||
**Multiple selection:**
|
||||
|
||||
```go
|
||||
paths, err := app.OpenFileDialog().
|
||||
paths, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Images").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForMultipleSelection()
|
||||
|
||||
for _, path := range paths {
|
||||
processFile(path)
|
||||
if err == nil {
|
||||
for _, path := range paths {
|
||||
processFile(path)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -154,30 +170,29 @@ for _, path := range paths {
|
|||
Choose where to save:
|
||||
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save Document").
|
||||
SetDefaultFilename("document.txt").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Text Files", Pattern: "*.txt"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("document.txt").
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err == nil {
|
||||
if err == nil && path != "" {
|
||||
saveFile(path)
|
||||
}
|
||||
```
|
||||
|
||||
### Select Folder dialog
|
||||
|
||||
Choose a directory:
|
||||
Choose a directory using the open file dialog with directory selection enabled:
|
||||
|
||||
```go
|
||||
path, err := app.SelectFolderDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Output Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err == nil {
|
||||
if err == nil && path != "" {
|
||||
exportToFolder(path)
|
||||
}
|
||||
```
|
||||
|
|
@ -187,42 +202,67 @@ if err == nil {
|
|||
### Title and Message
|
||||
|
||||
```go
|
||||
dialog := app.InfoDialog().
|
||||
dialog := app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("Operation completed successfully!")
|
||||
```
|
||||
|
||||
### Buttons
|
||||
|
||||
**Predefined buttons:**
|
||||
**Default button for simple dialogs:**
|
||||
|
||||
Info, warning, and error dialogs display a default "OK" button:
|
||||
|
||||
```go
|
||||
// OK button
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetMessage("Done!").
|
||||
Show()
|
||||
|
||||
// Yes/No buttons
|
||||
result, _ := app.QuestionDialog().
|
||||
SetMessage("Continue?").
|
||||
SetButtons("Yes", "No").
|
||||
Show()
|
||||
|
||||
// Custom buttons
|
||||
result, _ := app.QuestionDialog().
|
||||
SetMessage("Choose action").
|
||||
SetButtons("Save", "Don't Save", "Cancel").
|
||||
Show()
|
||||
```
|
||||
|
||||
**Default button:**
|
||||
**Custom buttons for question dialogs:**
|
||||
|
||||
Use `AddButton()` to add buttons, which returns a `*Button` you can configure with callbacks:
|
||||
|
||||
```go
|
||||
app.QuestionDialog().
|
||||
SetMessage("Delete file?").
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton("Cancel"). // Highlighted by default
|
||||
Show()
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Choose action")
|
||||
|
||||
save := dialog.AddButton("Save")
|
||||
save.OnClick(func() {
|
||||
saveDocument()
|
||||
})
|
||||
|
||||
dontSave := dialog.AddButton("Don't Save")
|
||||
dontSave.OnClick(func() {
|
||||
discardChanges()
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
// No callback needed - just dismisses dialog
|
||||
|
||||
dialog.SetDefaultButton(save)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
**Default and Cancel buttons:**
|
||||
|
||||
Use `SetDefaultButton()` to specify which button is highlighted and triggered by Enter.
|
||||
Use `SetCancelButton()` to specify which button is triggered by Escape.
|
||||
|
||||
```go
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Delete file?")
|
||||
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
performDelete()
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn) // Safe option highlighted by default
|
||||
dialog.SetCancelButton(cancelBtn) // Escape triggers Cancel
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
### Window Attachment
|
||||
|
|
@ -230,7 +270,7 @@ app.QuestionDialog().
|
|||
Attach dialog to specific window:
|
||||
|
||||
```go
|
||||
dialog := app.InfoDialog().
|
||||
dialog := app.Dialog.Info().
|
||||
SetMessage("Window-specific message").
|
||||
AttachToWindow(window)
|
||||
|
||||
|
|
@ -258,10 +298,12 @@ dialog.Show()
|
|||
**Example:**
|
||||
```go
|
||||
// Appears as sheet on macOS
|
||||
app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetMessage("Save changes?").
|
||||
AttachToWindow(window).
|
||||
Show()
|
||||
AttachToWindow(window)
|
||||
dialog.AddButton("Yes")
|
||||
dialog.AddButton("No")
|
||||
dialog.Show()
|
||||
```
|
||||
</TabItem>
|
||||
|
||||
|
|
@ -278,7 +320,7 @@ dialog.Show()
|
|||
**Example:**
|
||||
```go
|
||||
// Modal dialog on Windows
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Error").
|
||||
SetMessage("Operation failed").
|
||||
Show()
|
||||
|
|
@ -297,7 +339,7 @@ dialog.Show()
|
|||
**Example:**
|
||||
```go
|
||||
// GTK dialog on Linux
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetMessage("Update complete").
|
||||
Show()
|
||||
```
|
||||
|
|
@ -309,35 +351,41 @@ dialog.Show()
|
|||
### Confirm Before Destructive Action
|
||||
|
||||
```go
|
||||
func deleteFile(path string) error {
|
||||
result, err := app.QuestionDialog().
|
||||
func deleteFile(app *application.App, path string) {
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm Delete").
|
||||
SetMessage(fmt.Sprintf("Delete %s?", filepath.Base(path))).
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton("Cancel").
|
||||
Show()
|
||||
|
||||
if err != nil || result != "Delete" {
|
||||
return errors.New("cancelled")
|
||||
}
|
||||
|
||||
return os.Remove(path)
|
||||
SetMessage(fmt.Sprintf("Delete %s?", filepath.Base(path)))
|
||||
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
if err := os.Remove(path); err != nil {
|
||||
app.Dialog.Error().
|
||||
SetTitle("Delete Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
}
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(cancelBtn)
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling with dialog
|
||||
|
||||
```go
|
||||
func saveDocument(path string, data []byte) {
|
||||
func saveDocument(app *application.App, path string, data []byte) {
|
||||
if err := os.WriteFile(path, data, 0644); err != nil {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Save Failed").
|
||||
SetMessage(fmt.Sprintf("Could not save file: %v", err)).
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
app.InfoDialog().
|
||||
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("File saved successfully!").
|
||||
Show()
|
||||
|
|
@ -347,27 +395,29 @@ func saveDocument(path string, data []byte) {
|
|||
### File Selection with Validation
|
||||
|
||||
```go
|
||||
func selectImageFile() (string, error) {
|
||||
path, err := app.OpenFileDialog().
|
||||
func selectImageFile(app *application.App) (string, error) {
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.jpeg;*.gif"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif").
|
||||
PromptForSingleSelection()
|
||||
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
if path == "" {
|
||||
return "", errors.New("no file selected")
|
||||
}
|
||||
|
||||
// Validate file
|
||||
if !isValidImage(path) {
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Invalid File").
|
||||
SetMessage("Selected file is not a valid image.").
|
||||
Show()
|
||||
return "", errors.New("invalid image")
|
||||
}
|
||||
|
||||
|
||||
return path, nil
|
||||
}
|
||||
```
|
||||
|
|
@ -375,45 +425,43 @@ func selectImageFile() (string, error) {
|
|||
### Multi-Step dialog Flow
|
||||
|
||||
```go
|
||||
func exportData() {
|
||||
func exportData(app *application.App) {
|
||||
// Step 1: Confirm export
|
||||
result, _ := app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Export Data").
|
||||
SetMessage("Export all data to CSV?").
|
||||
SetButtons("Export", "Cancel").
|
||||
Show()
|
||||
|
||||
if result != "Export" {
|
||||
return
|
||||
}
|
||||
|
||||
// Step 2: Select destination
|
||||
path, err := app.SaveFileDialog().
|
||||
SetTitle("Save Export").
|
||||
SetDefaultFilename("export.csv").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "CSV Files", Pattern: "*.csv"},
|
||||
}).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Step 3: Perform export
|
||||
if err := performExport(path); err != nil {
|
||||
app.ErrorDialog().
|
||||
SetTitle("Export Failed").
|
||||
SetMessage(err.Error()).
|
||||
SetMessage("Export all data to CSV?")
|
||||
|
||||
exportBtn := dialog.AddButton("Export")
|
||||
exportBtn.OnClick(func() {
|
||||
// Step 2: Select destination
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetFilename("export.csv").
|
||||
AddFilter("CSV Files", "*.csv").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil || path == "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Step 3: Perform export
|
||||
if err := performExport(path); err != nil {
|
||||
app.Dialog.Error().
|
||||
SetTitle("Export Failed").
|
||||
SetMessage(err.Error()).
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
// Step 4: Success
|
||||
app.Dialog.Info().
|
||||
SetTitle("Export Complete").
|
||||
SetMessage("Data exported successfully!").
|
||||
Show()
|
||||
return
|
||||
}
|
||||
|
||||
// Step 4: Success
|
||||
app.InfoDialog().
|
||||
SetTitle("Export Complete").
|
||||
SetMessage("Data exported successfully!").
|
||||
Show()
|
||||
})
|
||||
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -261,96 +261,78 @@ app.OnApplicationEvent(application.EventApplicationShutdown, func(e *application
|
|||
})
|
||||
```
|
||||
|
||||
## dialog Methods
|
||||
## Dialog Methods
|
||||
|
||||
### InfoDialog()
|
||||
Dialogs are accessed through the `app.Dialog` manager. See [Dialogs API](/reference/dialogs/) for complete reference.
|
||||
|
||||
Creates an information dialog.
|
||||
### Message Dialogs
|
||||
|
||||
```go
|
||||
func (a *App) InfoDialog() InfoDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```go
|
||||
app.InfoDialog().
|
||||
// Information dialog
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("Operation completed!").
|
||||
Show()
|
||||
```
|
||||
|
||||
### QuestionDialog()
|
||||
|
||||
Creates a question dialog.
|
||||
|
||||
```go
|
||||
func (a *App) QuestionDialog() QuestionDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```go
|
||||
result, _ := app.QuestionDialog().
|
||||
SetTitle("Confirm").
|
||||
SetMessage("Continue?").
|
||||
SetButtons("Yes", "No").
|
||||
// Error dialog
|
||||
app.Dialog.Error().
|
||||
SetTitle("Error").
|
||||
SetMessage("Something went wrong.").
|
||||
Show()
|
||||
|
||||
if result == "Yes" {
|
||||
// Continue
|
||||
}
|
||||
// Warning dialog
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Warning").
|
||||
SetMessage("This action cannot be undone.").
|
||||
Show()
|
||||
```
|
||||
|
||||
### ErrorDialog()
|
||||
### Question Dialogs
|
||||
|
||||
Creates an error dialog.
|
||||
Question dialogs use button callbacks to handle user responses:
|
||||
|
||||
```go
|
||||
func (a *App) ErrorDialog() ErrorDialog
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Confirm").
|
||||
SetMessage("Continue?")
|
||||
|
||||
yes := dialog.AddButton("Yes")
|
||||
yes.OnClick(func() {
|
||||
// Handle yes
|
||||
})
|
||||
|
||||
no := dialog.AddButton("No")
|
||||
no.OnClick(func() {
|
||||
// Handle no
|
||||
})
|
||||
|
||||
dialog.SetDefaultButton(yes)
|
||||
dialog.SetCancelButton(no)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
### WarningDialog()
|
||||
|
||||
Creates a warning dialog.
|
||||
### File Dialogs
|
||||
|
||||
```go
|
||||
func (a *App) WarningDialog() WarningDialog
|
||||
```
|
||||
|
||||
### OpenFileDialog()
|
||||
|
||||
Creates a file open dialog.
|
||||
|
||||
```go
|
||||
func (a *App) OpenFileDialog() OpenFileDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
// Open file dialog
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select File").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
### SaveFileDialog()
|
||||
// Save file dialog
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetTitle("Save File").
|
||||
SetFilename("document.pdf").
|
||||
AddFilter("PDF", "*.pdf").
|
||||
PromptForSingleSelection()
|
||||
|
||||
Creates a file save dialog.
|
||||
|
||||
```go
|
||||
func (a *App) SaveFileDialog() SaveFileDialog
|
||||
```
|
||||
|
||||
### SelectFolderDialog()
|
||||
|
||||
Creates a folder selection dialog.
|
||||
|
||||
```go
|
||||
func (a *App) SelectFolderDialog() SelectFolderDialog
|
||||
// Folder selection (use OpenFile with directory options)
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
## Logger
|
||||
|
|
|
|||
|
|
@ -9,37 +9,50 @@ import { Card, CardGrid } from "@astrojs/starlight/components";
|
|||
|
||||
## Overview
|
||||
|
||||
The Dialogs API provides methods to show native file dialogs and message dialogs.
|
||||
The Dialogs API provides methods to show native file dialogs and message dialogs. Access dialogs through the `app.Dialog` manager.
|
||||
|
||||
**Dialog Types:**
|
||||
- **File Dialogs** - Open, Save, and Select Folder dialogs
|
||||
- **File Dialogs** - Open and Save dialogs
|
||||
- **Message Dialogs** - Info, Error, Warning, and Question dialogs
|
||||
|
||||
All dialogs are **native OS dialogs** that match the platform's look and feel.
|
||||
|
||||
## Accessing Dialogs
|
||||
|
||||
Dialogs are accessed through the `app.Dialog` manager:
|
||||
|
||||
```go
|
||||
app.Dialog.OpenFile()
|
||||
app.Dialog.SaveFile()
|
||||
app.Dialog.Info()
|
||||
app.Dialog.Question()
|
||||
app.Dialog.Warning()
|
||||
app.Dialog.Error()
|
||||
```
|
||||
|
||||
## File Dialogs
|
||||
|
||||
### OpenFileDialog()
|
||||
### OpenFile()
|
||||
|
||||
Creates a file open dialog.
|
||||
|
||||
```go
|
||||
func (a *App) OpenFileDialog() *OpenFileDialog
|
||||
func (dm *DialogManager) OpenFile() *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog := app.OpenFileDialog()
|
||||
dialog := app.Dialog.OpenFile()
|
||||
```
|
||||
|
||||
### OpenFileDialog Methods
|
||||
### OpenFileDialogStruct Methods
|
||||
|
||||
#### SetTitle()
|
||||
|
||||
Sets the dialog title.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialog) SetTitle(title string) *OpenFileDialog
|
||||
func (d *OpenFileDialogStruct) SetTitle(title string) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
|
@ -47,43 +60,87 @@ func (d *OpenFileDialog) SetTitle(title string) *OpenFileDialog
|
|||
dialog.SetTitle("Select Image")
|
||||
```
|
||||
|
||||
#### SetFilters()
|
||||
#### AddFilter()
|
||||
|
||||
Sets file type filters.
|
||||
Adds a file type filter.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialog) SetFilters(filters []FileFilter) *OpenFileDialog
|
||||
func (d *OpenFileDialogStruct) AddFilter(displayName, pattern string) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
**FileFilter structure:**
|
||||
```go
|
||||
type FileFilter struct {
|
||||
DisplayName string // "Images", "Documents", etc.
|
||||
Pattern string // "*.png;*.jpg", "*.pdf;*.doc", etc.
|
||||
}
|
||||
```
|
||||
**Parameters:**
|
||||
- `displayName` - Filter description shown to user (e.g., "Images", "Documents")
|
||||
- `pattern` - Semicolon-separated list of extensions (e.g., "*.png;*.jpg")
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog.SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.gif"},
|
||||
{DisplayName: "Documents", Pattern: "*.pdf;*.docx"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
})
|
||||
dialog.AddFilter("Images", "*.png;*.jpg;*.gif").
|
||||
AddFilter("Documents", "*.pdf;*.docx").
|
||||
AddFilter("All Files", "*.*")
|
||||
```
|
||||
|
||||
#### SetDefaultDirectory()
|
||||
#### SetDirectory()
|
||||
|
||||
Sets the initial directory.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialog) SetDefaultDirectory(path string) *OpenFileDialog
|
||||
func (d *OpenFileDialogStruct) SetDirectory(directory string) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
dialog.SetDefaultDirectory(homeDir)
|
||||
dialog.SetDirectory(homeDir)
|
||||
```
|
||||
|
||||
#### CanChooseDirectories()
|
||||
|
||||
Enables or disables directory selection.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialogStruct) CanChooseDirectories(canChooseDirectories bool) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
**Example (folder selection):**
|
||||
```go
|
||||
// Select folders instead of files
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
```
|
||||
|
||||
#### CanChooseFiles()
|
||||
|
||||
Enables or disables file selection.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialogStruct) CanChooseFiles(canChooseFiles bool) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
#### CanCreateDirectories()
|
||||
|
||||
Enables or disables creating new directories.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
#### ShowHiddenFiles()
|
||||
|
||||
Shows or hides hidden files.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
#### AttachToWindow()
|
||||
|
||||
Attaches the dialog to a specific window.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialogStruct) AttachToWindow(window Window) *OpenFileDialogStruct
|
||||
```
|
||||
|
||||
#### PromptForSingleSelection()
|
||||
|
|
@ -91,20 +148,18 @@ dialog.SetDefaultDirectory(homeDir)
|
|||
Shows the dialog and returns the selected file.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialog) PromptForSingleSelection() (string, error)
|
||||
func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error)
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
- `string` - Selected file path
|
||||
- `error` - Error if cancelled or failed
|
||||
- `string` - Selected file path (empty if cancelled)
|
||||
- `error` - Error if dialog failed
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
path, err := app.OpenFileDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.gif"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.gif").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -121,20 +176,18 @@ processFile(path)
|
|||
Shows the dialog and returns multiple selected files.
|
||||
|
||||
```go
|
||||
func (d *OpenFileDialog) PromptForMultipleSelection() ([]string, error)
|
||||
func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error)
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
- `[]string` - Array of selected file paths
|
||||
- `error` - Error if cancelled or failed
|
||||
- `error` - Error if dialog failed
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
paths, err := app.OpenFileDialog().
|
||||
paths, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Images").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForMultipleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -146,56 +199,70 @@ for _, path := range paths {
|
|||
}
|
||||
```
|
||||
|
||||
### SaveFileDialog()
|
||||
### SaveFile()
|
||||
|
||||
Creates a file save dialog.
|
||||
|
||||
```go
|
||||
func (a *App) SaveFileDialog() *SaveFileDialog
|
||||
func (dm *DialogManager) SaveFile() *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog := app.SaveFileDialog()
|
||||
dialog := app.Dialog.SaveFile()
|
||||
```
|
||||
|
||||
### SaveFileDialog Methods
|
||||
### SaveFileDialogStruct Methods
|
||||
|
||||
#### SetTitle()
|
||||
|
||||
Sets the dialog title.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialog) SetTitle(title string) *SaveFileDialog
|
||||
func (d *SaveFileDialogStruct) SetTitle(title string) *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
#### SetDefaultFilename()
|
||||
#### SetFilename()
|
||||
|
||||
Sets the default filename.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialog) SetDefaultFilename(filename string) *SaveFileDialog
|
||||
func (d *SaveFileDialogStruct) SetFilename(filename string) *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog.SetDefaultFilename("document.pdf")
|
||||
dialog.SetFilename("document.pdf")
|
||||
```
|
||||
|
||||
#### SetFilters()
|
||||
#### AddFilter()
|
||||
|
||||
Sets file type filters (same as OpenFileDialog).
|
||||
Adds a file type filter.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialog) SetFilters(filters []FileFilter) *SaveFileDialog
|
||||
func (d *SaveFileDialogStruct) AddFilter(displayName, pattern string) *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
#### SetDefaultDirectory()
|
||||
**Example:**
|
||||
```go
|
||||
dialog.AddFilter("PDF Document", "*.pdf").
|
||||
AddFilter("Text Document", "*.txt")
|
||||
```
|
||||
|
||||
Sets the initial directory (same as OpenFileDialog).
|
||||
#### SetDirectory()
|
||||
|
||||
Sets the initial directory.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialog) SetDefaultDirectory(path string) *SaveFileDialog
|
||||
func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
#### AttachToWindow()
|
||||
|
||||
Attaches the dialog to a specific window.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialogStruct) AttachToWindow(window Window) *SaveFileDialogStruct
|
||||
```
|
||||
|
||||
#### PromptForSingleSelection()
|
||||
|
|
@ -203,17 +270,15 @@ func (d *SaveFileDialog) SetDefaultDirectory(path string) *SaveFileDialog
|
|||
Shows the dialog and returns the save path.
|
||||
|
||||
```go
|
||||
func (d *SaveFileDialog) PromptForSingleSelection() (string, error)
|
||||
func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error)
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
path, err := app.SaveFileDialog().
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetTitle("Save Document").
|
||||
SetDefaultFilename("untitled.pdf").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "PDF Document", Pattern: "*.pdf"},
|
||||
}).
|
||||
SetFilename("untitled.pdf").
|
||||
AddFilter("PDF Document", "*.pdf").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -225,49 +290,15 @@ if err != nil {
|
|||
saveDocument(path)
|
||||
```
|
||||
|
||||
### SelectFolderDialog()
|
||||
### Folder Selection
|
||||
|
||||
Creates a folder selection dialog.
|
||||
There is no separate `SelectFolderDialog`. Use `OpenFile()` with directory options:
|
||||
|
||||
```go
|
||||
func (a *App) SelectFolderDialog() *SelectFolderDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog := app.SelectFolderDialog()
|
||||
```
|
||||
|
||||
### SelectFolderDialog Methods
|
||||
|
||||
#### SetTitle()
|
||||
|
||||
Sets the dialog title.
|
||||
|
||||
```go
|
||||
func (d *SelectFolderDialog) SetTitle(title string) *SelectFolderDialog
|
||||
```
|
||||
|
||||
#### SetDefaultDirectory()
|
||||
|
||||
Sets the initial directory.
|
||||
|
||||
```go
|
||||
func (d *SelectFolderDialog) SetDefaultDirectory(path string) *SelectFolderDialog
|
||||
```
|
||||
|
||||
#### PromptForSingleSelection()
|
||||
|
||||
Shows the dialog and returns the selected folder.
|
||||
|
||||
```go
|
||||
func (d *SelectFolderDialog) PromptForSingleSelection() (string, error)
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
path, err := app.SelectFolderDialog().
|
||||
path, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Output Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -281,105 +312,98 @@ outputDir = path
|
|||
|
||||
## Message Dialogs
|
||||
|
||||
### InfoDialog()
|
||||
All message dialogs return `*MessageDialog` and share the same methods.
|
||||
|
||||
### Info()
|
||||
|
||||
Creates an information dialog.
|
||||
|
||||
```go
|
||||
func (a *App) InfoDialog() *InfoDialog
|
||||
func (dm *DialogManager) Info() *MessageDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog := app.InfoDialog()
|
||||
```
|
||||
|
||||
### InfoDialog Methods
|
||||
|
||||
#### SetTitle()
|
||||
|
||||
Sets the dialog title.
|
||||
|
||||
```go
|
||||
func (d *InfoDialog) SetTitle(title string) *InfoDialog
|
||||
```
|
||||
|
||||
#### SetMessage()
|
||||
|
||||
Sets the dialog message.
|
||||
|
||||
```go
|
||||
func (d *InfoDialog) SetMessage(message string) *InfoDialog
|
||||
```
|
||||
|
||||
#### Show()
|
||||
|
||||
Shows the dialog.
|
||||
|
||||
```go
|
||||
func (d *InfoDialog) Show()
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("File saved successfully!").
|
||||
Show()
|
||||
```
|
||||
|
||||
### ErrorDialog()
|
||||
### Error()
|
||||
|
||||
Creates an error dialog.
|
||||
|
||||
```go
|
||||
func (a *App) ErrorDialog() *ErrorDialog
|
||||
func (dm *DialogManager) Error() *MessageDialog
|
||||
```
|
||||
|
||||
**Methods:** Same as InfoDialog (SetTitle, SetMessage, Show)
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Error").
|
||||
SetMessage("Failed to save file: " + err.Error()).
|
||||
Show()
|
||||
```
|
||||
|
||||
### WarningDialog()
|
||||
### Warning()
|
||||
|
||||
Creates a warning dialog.
|
||||
|
||||
```go
|
||||
func (a *App) WarningDialog() *WarningDialog
|
||||
func (dm *DialogManager) Warning() *MessageDialog
|
||||
```
|
||||
|
||||
**Methods:** Same as InfoDialog (SetTitle, SetMessage, Show)
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
app.WarningDialog().
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Warning").
|
||||
SetMessage("This action cannot be undone.").
|
||||
Show()
|
||||
```
|
||||
|
||||
### QuestionDialog()
|
||||
### Question()
|
||||
|
||||
Creates a question dialog with custom buttons.
|
||||
|
||||
```go
|
||||
func (a *App) QuestionDialog() *QuestionDialog
|
||||
func (dm *DialogManager) Question() *MessageDialog
|
||||
```
|
||||
|
||||
### QuestionDialog Methods
|
||||
**Example:**
|
||||
```go
|
||||
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() {
|
||||
// Continue without saving
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
cancel.OnClick(func() {
|
||||
// Do nothing
|
||||
})
|
||||
|
||||
dialog.SetDefaultButton(save)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
```
|
||||
|
||||
### MessageDialog Methods
|
||||
|
||||
#### SetTitle()
|
||||
|
||||
Sets the dialog title.
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) SetTitle(title string) *QuestionDialog
|
||||
func (d *MessageDialog) SetTitle(title string) *MessageDialog
|
||||
```
|
||||
|
||||
#### SetMessage()
|
||||
|
|
@ -387,24 +411,33 @@ func (d *QuestionDialog) SetTitle(title string) *QuestionDialog
|
|||
Sets the dialog message.
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) SetMessage(message string) *QuestionDialog
|
||||
func (d *MessageDialog) SetMessage(message string) *MessageDialog
|
||||
```
|
||||
|
||||
#### SetButtons()
|
||||
#### SetIcon()
|
||||
|
||||
Sets the button labels.
|
||||
Sets a custom icon for the dialog.
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) SetButtons(buttons ...string) *QuestionDialog
|
||||
func (d *MessageDialog) SetIcon(icon []byte) *MessageDialog
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `buttons` - Variable number of button labels
|
||||
#### AddButton()
|
||||
|
||||
Adds a button to the dialog and returns the button for configuration.
|
||||
|
||||
```go
|
||||
func (d *MessageDialog) AddButton(label string) *Button
|
||||
```
|
||||
|
||||
**Returns:** `*Button` - The button instance for further configuration
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
dialog.SetButtons("Yes", "No")
|
||||
dialog.SetButtons("Save", "Don't Save", "Cancel")
|
||||
button := dialog.AddButton("OK")
|
||||
button.OnClick(func() {
|
||||
// Handle click
|
||||
})
|
||||
```
|
||||
|
||||
#### SetDefaultButton()
|
||||
|
|
@ -412,13 +445,14 @@ dialog.SetButtons("Save", "Don't Save", "Cancel")
|
|||
Sets which button is the default (activated by pressing Enter).
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) SetDefaultButton(index int) *QuestionDialog
|
||||
func (d *MessageDialog) SetDefaultButton(button *Button) *MessageDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
// Make "Yes" the default button
|
||||
dialog.SetButtons("Yes", "No").SetDefaultButton(0)
|
||||
yes := dialog.AddButton("Yes")
|
||||
no := dialog.AddButton("No")
|
||||
dialog.SetDefaultButton(yes)
|
||||
```
|
||||
|
||||
#### SetCancelButton()
|
||||
|
|
@ -426,49 +460,58 @@ dialog.SetButtons("Yes", "No").SetDefaultButton(0)
|
|||
Sets which button is the cancel button (activated by pressing Escape).
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) SetCancelButton(index int) *QuestionDialog
|
||||
func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialog
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
// Make "Cancel" the cancel button
|
||||
dialog.SetButtons("Save", "Don't Save", "Cancel").SetCancelButton(2)
|
||||
ok := dialog.AddButton("OK")
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
dialog.SetCancelButton(cancel)
|
||||
```
|
||||
|
||||
#### AttachToWindow()
|
||||
|
||||
Attaches the dialog to a specific window.
|
||||
|
||||
```go
|
||||
func (d *MessageDialog) AttachToWindow(window Window) *MessageDialog
|
||||
```
|
||||
|
||||
#### Show()
|
||||
|
||||
Shows the dialog and returns the selected button.
|
||||
Shows the dialog. Button callbacks handle user responses.
|
||||
|
||||
```go
|
||||
func (d *QuestionDialog) Show() (string, error)
|
||||
func (d *MessageDialog) Show()
|
||||
```
|
||||
|
||||
**Returns:**
|
||||
- `string` - The label of the button that was clicked
|
||||
- `error` - Error if dialog failed to show
|
||||
**Note:** `Show()` does not return a value. Use button callbacks to handle user responses.
|
||||
|
||||
### Button Methods
|
||||
|
||||
#### OnClick()
|
||||
|
||||
Sets the callback function for when the button is clicked.
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
result, err := app.QuestionDialog().
|
||||
SetTitle("Confirm").
|
||||
SetMessage("Do you want to save changes?").
|
||||
SetButtons("Save", "Don't Save", "Cancel").
|
||||
SetDefaultButton(0).
|
||||
SetCancelButton(2).
|
||||
Show()
|
||||
func (b *Button) OnClick(callback func()) *Button
|
||||
```
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
#### SetAsDefault()
|
||||
|
||||
switch result {
|
||||
case "Save":
|
||||
saveDocument()
|
||||
case "Don't Save":
|
||||
// Continue without saving
|
||||
case "Cancel":
|
||||
return
|
||||
}
|
||||
Marks this button as the default button.
|
||||
|
||||
```go
|
||||
func (b *Button) SetAsDefault() *Button
|
||||
```
|
||||
|
||||
#### SetAsCancel()
|
||||
|
||||
Marks this button as the cancel button.
|
||||
|
||||
```go
|
||||
func (b *Button) SetAsCancel() *Button
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
|
@ -477,16 +520,14 @@ case "Cancel":
|
|||
|
||||
```go
|
||||
type FileService struct {
|
||||
app *application.Application
|
||||
app *application.App
|
||||
}
|
||||
|
||||
func (s *FileService) OpenImage() (string, error) {
|
||||
path, err := s.app.OpenFileDialog().
|
||||
path, err := s.app.Dialog.OpenFile().
|
||||
SetTitle("Select Image").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg;*.jpeg;*.gif"},
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif").
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -497,13 +538,11 @@ func (s *FileService) OpenImage() (string, error) {
|
|||
}
|
||||
|
||||
func (s *FileService) SaveDocument(defaultName string) (string, error) {
|
||||
path, err := s.app.SaveFileDialog().
|
||||
path, err := s.app.Dialog.SaveFile().
|
||||
SetTitle("Save Document").
|
||||
SetDefaultFilename(defaultName).
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "PDF Document", Pattern: "*.pdf"},
|
||||
{DisplayName: "Text Document", Pattern: "*.txt"},
|
||||
}).
|
||||
SetFilename(defaultName).
|
||||
AddFilter("PDF Document", "*.pdf").
|
||||
AddFilter("Text Document", "*.txt").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -514,8 +553,10 @@ func (s *FileService) SaveDocument(defaultName string) (string, error) {
|
|||
}
|
||||
|
||||
func (s *FileService) SelectOutputFolder() (string, error) {
|
||||
path, err := s.app.SelectFolderDialog().
|
||||
path, err := s.app.Dialog.OpenFile().
|
||||
SetTitle("Select Output Folder").
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -529,64 +570,61 @@ func (s *FileService) SelectOutputFolder() (string, error) {
|
|||
### Confirmation Dialog Example
|
||||
|
||||
```go
|
||||
func (s *Service) DeleteItem(id string) error {
|
||||
// Confirm before deleting
|
||||
result, err := s.app.QuestionDialog().
|
||||
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?").
|
||||
SetButtons("Delete", "Cancel").
|
||||
SetDefaultButton(1). // Default to Cancel
|
||||
SetCancelButton(1).
|
||||
Show()
|
||||
SetMessage("Are you sure you want to delete this item?")
|
||||
|
||||
if err != nil || result == "Cancel" {
|
||||
return nil // User cancelled
|
||||
}
|
||||
deleteBtn := dialog.AddButton("Delete")
|
||||
deleteBtn.OnClick(func() {
|
||||
deleteFromDatabase(id)
|
||||
})
|
||||
|
||||
// Perform deletion
|
||||
return deleteFromDatabase(id)
|
||||
cancelBtn := dialog.AddButton("Cancel")
|
||||
// Cancel does nothing
|
||||
|
||||
dialog.SetDefaultButton(cancelBtn) // Default to Cancel for safety
|
||||
dialog.SetCancelButton(cancelBtn)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Save Changes Dialog
|
||||
|
||||
```go
|
||||
func (s *Editor) PromptSaveChanges() (bool, error) {
|
||||
result, err := s.app.QuestionDialog().
|
||||
func (s *Editor) PromptSaveChanges(app *application.App) {
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Unsaved Changes").
|
||||
SetMessage("Do you want to save your changes before closing?").
|
||||
SetButtons("Save", "Don't Save", "Cancel").
|
||||
SetDefaultButton(0).
|
||||
SetCancelButton(2).
|
||||
Show()
|
||||
SetMessage("Do you want to save your changes before closing?")
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
save := dialog.AddButton("Save")
|
||||
save.OnClick(func() {
|
||||
s.Save()
|
||||
s.Close()
|
||||
})
|
||||
|
||||
switch result {
|
||||
case "Save":
|
||||
return s.Save()
|
||||
case "Don't Save":
|
||||
return true, nil
|
||||
case "Cancel":
|
||||
return false, nil
|
||||
}
|
||||
dontSave := dialog.AddButton("Don't Save")
|
||||
dontSave.OnClick(func() {
|
||||
s.Close()
|
||||
})
|
||||
|
||||
return false, nil
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
// Cancel does nothing, dialog closes
|
||||
|
||||
dialog.SetDefaultButton(save)
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
}
|
||||
```
|
||||
|
||||
### Multi-File Processing
|
||||
|
||||
```go
|
||||
func (s *Service) ProcessMultipleFiles() error {
|
||||
func (s *Service) ProcessMultipleFiles(app *application.App) error {
|
||||
// Select multiple files
|
||||
paths, err := s.app.OpenFileDialog().
|
||||
paths, err := app.Dialog.OpenFile().
|
||||
SetTitle("Select Files to Process").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "Images", Pattern: "*.png;*.jpg"},
|
||||
}).
|
||||
AddFilter("Images", "*.png;*.jpg").
|
||||
PromptForMultipleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -594,7 +632,7 @@ func (s *Service) ProcessMultipleFiles() error {
|
|||
}
|
||||
|
||||
if len(paths) == 0 {
|
||||
s.app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("No Files Selected").
|
||||
SetMessage("Please select at least one file.").
|
||||
Show()
|
||||
|
|
@ -602,25 +640,19 @@ func (s *Service) ProcessMultipleFiles() error {
|
|||
}
|
||||
|
||||
// Process files
|
||||
for i, path := range paths {
|
||||
for _, path := range paths {
|
||||
err := processFile(path)
|
||||
if err != nil {
|
||||
s.app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Processing Error").
|
||||
SetMessage(fmt.Sprintf("Failed to process %s: %v", path, err)).
|
||||
Show()
|
||||
continue
|
||||
}
|
||||
|
||||
// Show progress
|
||||
s.app.EmitEvent("progress", map[string]interface{}{
|
||||
"current": i + 1,
|
||||
"total": len(paths),
|
||||
})
|
||||
}
|
||||
|
||||
// Show completion
|
||||
s.app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Complete").
|
||||
SetMessage(fmt.Sprintf("Successfully processed %d files", len(paths))).
|
||||
Show()
|
||||
|
|
@ -632,14 +664,12 @@ func (s *Service) ProcessMultipleFiles() error {
|
|||
### Error Handling with Dialogs
|
||||
|
||||
```go
|
||||
func (s *Service) SaveFile(data []byte) error {
|
||||
func (s *Service) SaveFile(app *application.App, data []byte) error {
|
||||
// Select save location
|
||||
path, err := s.app.SaveFileDialog().
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetTitle("Save File").
|
||||
SetDefaultFilename("data.json").
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "JSON File", Pattern: "*.json"},
|
||||
}).
|
||||
SetFilename("data.json").
|
||||
AddFilter("JSON File", "*.json").
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -651,7 +681,7 @@ func (s *Service) SaveFile(data []byte) error {
|
|||
err = os.WriteFile(path, data, 0644)
|
||||
if err != nil {
|
||||
// Show error dialog
|
||||
s.app.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetTitle("Save Failed").
|
||||
SetMessage(fmt.Sprintf("Could not save file: %v", err)).
|
||||
Show()
|
||||
|
|
@ -659,7 +689,7 @@ func (s *Service) SaveFile(data []byte) error {
|
|||
}
|
||||
|
||||
// Show success
|
||||
s.app.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("Success").
|
||||
SetMessage("File saved successfully!").
|
||||
Show()
|
||||
|
|
@ -692,33 +722,32 @@ func (s *Service) GetDefaultDirectory() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Service) OpenWithDefaults() (string, error) {
|
||||
return s.app.OpenFileDialog().
|
||||
func (s *Service) OpenWithDefaults(app *application.App) (string, error) {
|
||||
return app.Dialog.OpenFile().
|
||||
SetTitle("Open File").
|
||||
SetDefaultDirectory(s.GetDefaultDirectory()).
|
||||
SetFilters([]application.FileFilter{
|
||||
{DisplayName: "All Files", Pattern: "*.*"},
|
||||
}).
|
||||
SetDirectory(s.GetDefaultDirectory()).
|
||||
AddFilter("All Files", "*.*").
|
||||
PromptForSingleSelection()
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### ✅ Do
|
||||
### Do
|
||||
|
||||
- **Use native dialogs** - They match the platform's look and feel
|
||||
- **Provide clear titles** - Help users understand the purpose
|
||||
- **Set appropriate filters** - Guide users to correct file types
|
||||
- **Handle cancellation** - Check for errors (user may cancel)
|
||||
- **Show confirmation for destructive actions** - Use QuestionDialog
|
||||
- **Provide feedback** - Use InfoDialog for success messages
|
||||
- **Show confirmation for destructive actions** - Use Question dialogs
|
||||
- **Provide feedback** - Use Info dialogs for success messages
|
||||
- **Set sensible defaults** - Default directory, filename, etc.
|
||||
- **Use callbacks for button actions** - Handle user responses properly
|
||||
|
||||
### ❌ Don't
|
||||
### Don't
|
||||
|
||||
- **Don't ignore errors** - User cancellation returns an error
|
||||
- **Don't use ambiguous button labels** - "OK" vs "Save"/"Cancel"
|
||||
- **Don't use ambiguous button labels** - Be specific: "Save"/"Cancel"
|
||||
- **Don't overuse dialogs** - They interrupt workflow
|
||||
- **Don't show errors for cancellation** - It's a normal action
|
||||
- **Don't forget file filters** - Help users find the right files
|
||||
|
|
@ -749,14 +778,14 @@ func (s *Service) OpenWithDefaults() (string, error) {
|
|||
### "Save As" Pattern
|
||||
|
||||
```go
|
||||
func (s *Service) SaveAs(currentPath string) (string, error) {
|
||||
func (s *Service) SaveAs(app *application.App, currentPath string) (string, error) {
|
||||
// Extract filename from current path
|
||||
filename := filepath.Base(currentPath)
|
||||
|
||||
// Show save dialog
|
||||
path, err := s.app.SaveFileDialog().
|
||||
path, err := app.Dialog.SaveFile().
|
||||
SetTitle("Save As").
|
||||
SetDefaultFilename(filename).
|
||||
SetFilename(filename).
|
||||
PromptForSingleSelection()
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -770,18 +799,21 @@ func (s *Service) SaveAs(currentPath string) (string, error) {
|
|||
### "Open Recent" Pattern
|
||||
|
||||
```go
|
||||
func (s *Service) OpenRecent(recentPath string) error {
|
||||
func (s *Service) OpenRecent(app *application.App, recentPath string) error {
|
||||
// Check if file still exists
|
||||
if _, err := os.Stat(recentPath); os.IsNotExist(err) {
|
||||
result, _ := s.app.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("File Not Found").
|
||||
SetMessage("The file no longer exists. Remove from recent files?").
|
||||
SetButtons("Remove", "Cancel").
|
||||
Show()
|
||||
SetMessage("The file no longer exists. Remove from recent files?")
|
||||
|
||||
if result == "Remove" {
|
||||
remove := dialog.AddButton("Remove")
|
||||
remove.OnClick(func() {
|
||||
s.removeFromRecent(recentPath)
|
||||
}
|
||||
})
|
||||
|
||||
cancel := dialog.AddButton("Cancel")
|
||||
dialog.SetCancelButton(cancel)
|
||||
dialog.Show()
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ After processing, the content will be moved to the main changelog and this file
|
|||
|
||||
## Changed
|
||||
<!-- Changes in existing functionality -->
|
||||
- **BREAKING**: Remove package-level dialog functions (`application.InfoDialog()`, `application.QuestionDialog()`, etc.). Use the `app.Dialog` manager instead: `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`, `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()`
|
||||
- Update dialogs documentation to match actual API: use `app.Dialog.*`, `AddButton()` with callbacks (not `SetButtons()`), `SetDefaultButton(*Button)` (not string), `AddFilter()` (not `SetFilters()`), `SetFilename()` (not `SetDefaultFilename()`), and `app.Dialog.OpenFile().CanChooseDirectories(true)` for folder selection
|
||||
|
||||
## Fixed
|
||||
<!-- Bug fixes -->
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ func main() {
|
|||
sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
width, height := w.Size()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ func main() {
|
|||
positionMenu.Add("Get Relative Position").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
x, y := w.RelativePosition()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Relative Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Relative Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -241,24 +241,24 @@ func main() {
|
|||
stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) {
|
||||
screen := app.Screen.GetPrimary()
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
})
|
||||
stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) {
|
||||
screens := app.Screen.GetAll()
|
||||
for _, screen := range screens {
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
}
|
||||
})
|
||||
stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
screen, err := w.GetScreen()
|
||||
if err != nil {
|
||||
application.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
})
|
||||
})
|
||||
app.Window.New()
|
||||
|
|
|
|||
|
|
@ -30,28 +30,28 @@ func main() {
|
|||
setClipboardMenu.Add("Set Text 'Hello'").OnClick(func(ctx *application.Context) {
|
||||
success := app.Clipboard.SetText("Hello")
|
||||
if !success {
|
||||
application.InfoDialog().SetMessage("Failed to set clipboard text").Show()
|
||||
app.Dialog.Info().SetMessage("Failed to set clipboard text").Show()
|
||||
}
|
||||
})
|
||||
setClipboardMenu.Add("Set Text 'World'").OnClick(func(ctx *application.Context) {
|
||||
success := app.Clipboard.SetText("World")
|
||||
if !success {
|
||||
application.InfoDialog().SetMessage("Failed to set clipboard text").Show()
|
||||
app.Dialog.Info().SetMessage("Failed to set clipboard text").Show()
|
||||
}
|
||||
})
|
||||
setClipboardMenu.Add("Set Text (current time)").OnClick(func(ctx *application.Context) {
|
||||
success := app.Clipboard.SetText(time.Now().String())
|
||||
if !success {
|
||||
application.InfoDialog().SetMessage("Failed to set clipboard text").Show()
|
||||
app.Dialog.Info().SetMessage("Failed to set clipboard text").Show()
|
||||
}
|
||||
})
|
||||
getClipboardMenu := menu.AddSubmenu("Get Clipboard")
|
||||
getClipboardMenu.Add("Get Text").OnClick(func(ctx *application.Context) {
|
||||
result, ok := app.Clipboard.Text()
|
||||
if !ok {
|
||||
application.InfoDialog().SetMessage("Failed to get clipboard text").Show()
|
||||
app.Dialog.Info().SetMessage("Failed to get clipboard text").Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("Got:\n\n" + result).Show()
|
||||
app.Dialog.Info().SetMessage("Got:\n\n" + result).Show()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -59,9 +59,9 @@ func main() {
|
|||
clearClipboardMenu.Add("Clear Text").OnClick(func(ctx *application.Context) {
|
||||
success := app.Clipboard.SetText("")
|
||||
if success {
|
||||
application.InfoDialog().SetMessage("Clipboard text cleared").Show()
|
||||
app.Dialog.Info().SetMessage("Clipboard text cleared").Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("Clipboard text not cleared").Show()
|
||||
app.Dialog.Info().SetMessage("Clipboard text not cleared").Show()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func main() {
|
|||
|
||||
// Test 1: Basic file open with no filters (no window)
|
||||
testMenu.Add("1. Basic Open (No Window)").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
PromptForSingleSelection()
|
||||
showResult("Basic Open", result, err, nil)
|
||||
|
|
@ -52,7 +52,7 @@ func main() {
|
|||
|
||||
// Test 1b: Basic file open with window
|
||||
testMenu.Add("1b. Basic Open (With Window)").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
AttachToWindow(mainWindow).
|
||||
PromptForSingleSelection()
|
||||
|
|
@ -61,7 +61,7 @@ func main() {
|
|||
|
||||
// Test 2: Open with single extension filter
|
||||
testMenu.Add("2. Single Filter").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -71,7 +71,7 @@ func main() {
|
|||
|
||||
// Test 3: Open with multiple extension filter
|
||||
testMenu.Add("3. Multiple Filter").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
AddFilter("Documents", "*.txt;*.md;*.doc;*.docx").
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -81,7 +81,7 @@ func main() {
|
|||
|
||||
// Test 4: Multiple file selection
|
||||
testMenu.Add("4. Multiple Selection").OnClick(func(ctx *application.Context) {
|
||||
results, err := application.OpenFileDialog().
|
||||
results, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
AddFilter("Images", "*.png;*.jpg;*.jpeg").
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -95,7 +95,7 @@ func main() {
|
|||
|
||||
// Test 5: Directory selection
|
||||
testMenu.Add("5. Directory Selection").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -105,7 +105,7 @@ func main() {
|
|||
|
||||
// Test 6: Save dialog with extension
|
||||
testMenu.Add("6. Save Dialog").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.SaveFileDialog().
|
||||
result, err := app.Dialog.SaveFile().
|
||||
SetFilename("test.txt").
|
||||
AddFilter("Text Files", "*.txt").
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -115,7 +115,7 @@ func main() {
|
|||
|
||||
// Test 7: Complex filters
|
||||
testMenu.Add("7. Complex Filters").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
AddFilter("All Documents", "*.txt;*.md;*.doc;*.docx;*.pdf").
|
||||
AddFilter("Text Files", "*.txt").
|
||||
|
|
@ -129,7 +129,7 @@ func main() {
|
|||
|
||||
// Test 8: Hidden files
|
||||
testMenu.Add("8. Show Hidden").OnClick(func(ctx *application.Context) {
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
ShowHiddenFiles(true).
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -140,7 +140,7 @@ func main() {
|
|||
// Test 9: Default directory
|
||||
testMenu.Add("9. Default Directory").OnClick(func(ctx *application.Context) {
|
||||
home, _ := os.UserHomeDir()
|
||||
result, err := application.OpenFileDialog().
|
||||
result, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
SetDirectory(home).
|
||||
AttachToWindow(mainWindow).
|
||||
|
|
@ -151,7 +151,7 @@ func main() {
|
|||
// Test 10: Full featured dialog
|
||||
testMenu.Add("10. Full Featured").OnClick(func(ctx *application.Context) {
|
||||
home, _ := os.UserHomeDir()
|
||||
dialog := application.OpenFileDialog().
|
||||
dialog := app.Dialog.OpenFile().
|
||||
SetTitle("Full Featured Dialog").
|
||||
SetDirectory(home).
|
||||
CanChooseFiles(true).
|
||||
|
|
@ -192,7 +192,7 @@ func showResult(test string, result string, err error, window *application.Webvi
|
|||
return
|
||||
}
|
||||
if result == "" {
|
||||
dialog := application.InfoDialog().
|
||||
dialog := application.Get().Dialog.Info().
|
||||
SetTitle(test).
|
||||
SetMessage("No file selected")
|
||||
if window != nil {
|
||||
|
|
@ -201,7 +201,7 @@ func showResult(test string, result string, err error, window *application.Webvi
|
|||
dialog.Show()
|
||||
return
|
||||
}
|
||||
dialog := application.InfoDialog().
|
||||
dialog := application.Get().Dialog.Info().
|
||||
SetTitle(test).
|
||||
SetMessage(fmt.Sprintf("Selected: %s\nType: %s", result, getFileType(result)))
|
||||
if window != nil {
|
||||
|
|
@ -212,7 +212,7 @@ func showResult(test string, result string, err error, window *application.Webvi
|
|||
|
||||
func showResults(test string, results []string, window *application.WebviewWindow) {
|
||||
if len(results) == 0 {
|
||||
dialog := application.InfoDialog().
|
||||
dialog := application.Get().Dialog.Info().
|
||||
SetTitle(test).
|
||||
SetMessage("No files selected")
|
||||
if window != nil {
|
||||
|
|
@ -226,7 +226,7 @@ func showResults(test string, results []string, window *application.WebviewWindo
|
|||
for _, result := range results {
|
||||
message.WriteString(fmt.Sprintf("%s (%s)\n", result, getFileType(result)))
|
||||
}
|
||||
dialog := application.InfoDialog().
|
||||
dialog := application.Get().Dialog.Info().
|
||||
SetTitle(test).
|
||||
SetMessage(message.String())
|
||||
if window != nil {
|
||||
|
|
@ -236,7 +236,7 @@ func showResults(test string, results []string, window *application.WebviewWindo
|
|||
}
|
||||
|
||||
func showError(test string, err error, window *application.WebviewWindow) {
|
||||
dialog := application.ErrorDialog().
|
||||
dialog := application.Get().Dialog.Error().
|
||||
SetTitle(test).
|
||||
SetMessage(fmt.Sprintf("Error: %v", err))
|
||||
if window != nil {
|
||||
|
|
@ -249,11 +249,8 @@ func getFileType(path string) string {
|
|||
if path == "" {
|
||||
return "unknown"
|
||||
}
|
||||
ext := strings.ToLower(filepath.Ext(path))
|
||||
ext := filepath.Ext(path)
|
||||
if ext == "" {
|
||||
if fi, err := os.Stat(path); err == nil && fi.IsDir() {
|
||||
return "directory"
|
||||
}
|
||||
return "no extension"
|
||||
}
|
||||
return ext
|
||||
|
|
|
|||
|
|
@ -36,24 +36,24 @@ func main() {
|
|||
// Let's make a "Demo" menu
|
||||
infoMenu := menu.AddSubmenu("Info")
|
||||
infoMenu.Add("Info").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.InfoDialog()
|
||||
dialog := app.Dialog.Info()
|
||||
dialog.SetTitle("Custom Title")
|
||||
dialog.SetMessage("This is a custom message")
|
||||
dialog.Show()
|
||||
})
|
||||
|
||||
infoMenu.Add("Info (Title only)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.InfoDialog()
|
||||
dialog := app.Dialog.Info()
|
||||
dialog.SetTitle("Custom Title")
|
||||
dialog.Show()
|
||||
})
|
||||
infoMenu.Add("Info (Message only)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.InfoDialog()
|
||||
dialog := app.Dialog.Info()
|
||||
dialog.SetMessage("This is a custom message")
|
||||
dialog.Show()
|
||||
})
|
||||
infoMenu.Add("Info (Custom Icon)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.InfoDialog()
|
||||
dialog := app.Dialog.Info()
|
||||
dialog.SetTitle("Custom Icon Example")
|
||||
dialog.SetMessage("Using a custom icon")
|
||||
dialog.SetIcon(icons.ApplicationDarkMode256)
|
||||
|
|
@ -65,14 +65,14 @@ func main() {
|
|||
|
||||
questionMenu := menu.AddSubmenu("Question")
|
||||
questionMenu.Add("Question (No default)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.QuestionDialog()
|
||||
dialog := app.Dialog.Question()
|
||||
dialog.SetMessage("No default button")
|
||||
dialog.AddButton("Yes")
|
||||
dialog.AddButton("No")
|
||||
dialog.Show()
|
||||
})
|
||||
questionMenu.Add("Question (Attached to Window)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.QuestionDialog()
|
||||
dialog := app.Dialog.Question()
|
||||
dialog.AttachToWindow(app.Window.Current())
|
||||
dialog.SetMessage("No default button")
|
||||
dialog.AddButton("Yes")
|
||||
|
|
@ -80,7 +80,7 @@ func main() {
|
|||
dialog.Show()
|
||||
})
|
||||
questionMenu.Add("Question (With Default)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.QuestionDialog()
|
||||
dialog := app.Dialog.Question()
|
||||
dialog.SetTitle("Quit")
|
||||
dialog.SetMessage("You have unsaved work. Are you sure you want to quit?")
|
||||
dialog.AddButton("Yes").OnClick(func() {
|
||||
|
|
@ -91,12 +91,12 @@ func main() {
|
|||
dialog.Show()
|
||||
})
|
||||
questionMenu.Add("Question (With Cancel)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.QuestionDialog().
|
||||
dialog := app.Dialog.Question().
|
||||
SetTitle("Update").
|
||||
SetMessage("The cancel button is selected when pressing escape")
|
||||
download := dialog.AddButton("📥 Download")
|
||||
download.OnClick(func() {
|
||||
application.InfoDialog().SetMessage("Downloading...").Show()
|
||||
app.Dialog.Info().SetMessage("Downloading...").Show()
|
||||
})
|
||||
no := dialog.AddButton("Cancel")
|
||||
dialog.SetDefaultButton(download)
|
||||
|
|
@ -104,15 +104,15 @@ func main() {
|
|||
dialog.Show()
|
||||
})
|
||||
questionMenu.Add("Question (Custom Icon)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.QuestionDialog()
|
||||
dialog := app.Dialog.Question()
|
||||
dialog.SetTitle("Custom Icon Example")
|
||||
dialog.SetMessage("Using a custom icon")
|
||||
dialog.SetIcon(icons.WailsLogoWhiteTransparent)
|
||||
likeIt := dialog.AddButton("I like it!").OnClick(func() {
|
||||
application.InfoDialog().SetMessage("Thanks!").Show()
|
||||
app.Dialog.Info().SetMessage("Thanks!").Show()
|
||||
})
|
||||
dialog.AddButton("Not so keen...").OnClick(func() {
|
||||
application.InfoDialog().SetMessage("Too bad!").Show()
|
||||
app.Dialog.Info().SetMessage("Too bad!").Show()
|
||||
})
|
||||
dialog.SetDefaultButton(likeIt)
|
||||
dialog.Show()
|
||||
|
|
@ -120,23 +120,23 @@ func main() {
|
|||
|
||||
warningMenu := menu.AddSubmenu("Warning")
|
||||
warningMenu.Add("Warning").OnClick(func(ctx *application.Context) {
|
||||
application.WarningDialog().
|
||||
app.Dialog.Warning().
|
||||
SetTitle("Custom Title").
|
||||
SetMessage("This is a custom message").
|
||||
Show()
|
||||
})
|
||||
warningMenu.Add("Warning (Title only)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.WarningDialog()
|
||||
dialog := app.Dialog.Warning()
|
||||
dialog.SetTitle("Custom Title")
|
||||
dialog.Show()
|
||||
})
|
||||
warningMenu.Add("Warning (Message only)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.WarningDialog()
|
||||
dialog := app.Dialog.Warning()
|
||||
dialog.SetMessage("This is a custom message")
|
||||
dialog.Show()
|
||||
})
|
||||
warningMenu.Add("Warning (Custom Icon)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.WarningDialog()
|
||||
dialog := app.Dialog.Warning()
|
||||
dialog.SetTitle("Custom Icon Example")
|
||||
dialog.SetMessage("Using a custom icon")
|
||||
dialog.SetIcon(icons.ApplicationLightMode256)
|
||||
|
|
@ -145,23 +145,23 @@ func main() {
|
|||
|
||||
errorMenu := menu.AddSubmenu("Error")
|
||||
errorMenu.Add("Error").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.ErrorDialog()
|
||||
dialog := app.Dialog.Error()
|
||||
dialog.SetTitle("Ooops")
|
||||
dialog.SetMessage("I accidentally the whole of Twitter")
|
||||
dialog.Show()
|
||||
})
|
||||
errorMenu.Add("Error (Title Only)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.ErrorDialog()
|
||||
dialog := app.Dialog.Error()
|
||||
dialog.SetTitle("Custom Title")
|
||||
dialog.Show()
|
||||
})
|
||||
errorMenu.Add("Error (Custom Message)").OnClick(func(ctx *application.Context) {
|
||||
application.ErrorDialog().
|
||||
app.Dialog.Error().
|
||||
SetMessage("This is a custom message").
|
||||
Show()
|
||||
})
|
||||
errorMenu.Add("Error (Custom Icon)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.ErrorDialog()
|
||||
dialog := app.Dialog.Error()
|
||||
dialog.SetTitle("Custom Icon Example")
|
||||
dialog.SetMessage("Using a custom icon")
|
||||
dialog.SetIcon(icons.WailsLogoWhite)
|
||||
|
|
@ -170,90 +170,90 @@ func main() {
|
|||
|
||||
openMenu := menu.AddSubmenu("Open")
|
||||
openMenu.Add("Open File").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
CanCreateDirectories(true).
|
||||
ShowHiddenFiles(true).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open File (Attach to window)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
CanCreateDirectories(true).
|
||||
ShowHiddenFiles(true).
|
||||
AttachToWindow(app.Window.Current()).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
CanCreateDirectories(true).
|
||||
ShowHiddenFiles(true).
|
||||
PromptForMultipleSelection()
|
||||
if len(result) > 0 {
|
||||
application.InfoDialog().SetMessage(strings.Join(result, ",")).Show()
|
||||
app.Dialog.Info().SetMessage(strings.Join(result, ",")).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No directory selected").Show()
|
||||
app.Dialog.Info().SetMessage("No directory selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseDirectories(true).
|
||||
CanCreateDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No directory selected").Show()
|
||||
app.Dialog.Info().SetMessage("No directory selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open Directory (Resolves Aliases)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.OpenFileDialog().
|
||||
result, _ := app.Dialog.OpenFile().
|
||||
CanChooseDirectories(true).
|
||||
CanCreateDirectories(true).
|
||||
CanChooseFiles(false).
|
||||
ResolvesAliases(true).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No directory selected").Show()
|
||||
app.Dialog.Info().SetMessage("No directory selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open File/Directory (Set Title)").OnClick(func(ctx *application.Context) {
|
||||
dialog := application.OpenFileDialog().
|
||||
dialog := app.Dialog.OpenFile().
|
||||
CanChooseDirectories(true).
|
||||
CanCreateDirectories(true).
|
||||
ResolvesAliases(true)
|
||||
|
|
@ -265,14 +265,14 @@ func main() {
|
|||
|
||||
result, _ := dialog.PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file/directory selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file/directory selected").Show()
|
||||
}
|
||||
})
|
||||
openMenu.Add("Open (Full Example)").OnClick(func(ctx *application.Context) {
|
||||
cwd, _ := os.Getwd()
|
||||
dialog := application.OpenFileDialog().
|
||||
dialog := app.Dialog.OpenFile().
|
||||
SetTitle("Select a file").
|
||||
SetMessage("Select a file to open").
|
||||
SetButtonText("Let's do this!").
|
||||
|
|
@ -294,46 +294,46 @@ func main() {
|
|||
|
||||
result, _ := dialog.PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
} else {
|
||||
application.InfoDialog().SetMessage("No file selected").Show()
|
||||
app.Dialog.Info().SetMessage("No file selected").Show()
|
||||
}
|
||||
})
|
||||
|
||||
saveMenu := menu.AddSubmenu("Save")
|
||||
saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.SaveFileDialog().
|
||||
result, _ := app.Dialog.SaveFile().
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
}
|
||||
})
|
||||
saveMenu.Add("Select File (Attach To WebviewWindow)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.SaveFileDialog().
|
||||
result, _ := app.Dialog.SaveFile().
|
||||
AttachToWindow(app.Window.Current()).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
}
|
||||
})
|
||||
saveMenu.Add("Select File (Show Hidden Files)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.SaveFileDialog().
|
||||
result, _ := app.Dialog.SaveFile().
|
||||
ShowHiddenFiles(true).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
}
|
||||
})
|
||||
saveMenu.Add("Select File (Cannot Create Directories)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.SaveFileDialog().
|
||||
result, _ := app.Dialog.SaveFile().
|
||||
CanCreateDirectories(false).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
}
|
||||
})
|
||||
saveMenu.Add("Select File (Full Example)").OnClick(func(ctx *application.Context) {
|
||||
result, _ := application.SaveFileDialog().
|
||||
result, _ := app.Dialog.SaveFile().
|
||||
CanCreateDirectories(false).
|
||||
ShowHiddenFiles(true).
|
||||
SetMessage("Select a file").
|
||||
|
|
@ -346,7 +346,7 @@ func main() {
|
|||
ShowHiddenFiles(true).
|
||||
PromptForSingleSelection()
|
||||
if result != "" {
|
||||
application.InfoDialog().SetMessage(result).Show()
|
||||
app.Dialog.Info().SetMessage(result).Show()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ import (
|
|||
"log"
|
||||
)
|
||||
|
||||
var app *application.App
|
||||
|
||||
func main() {
|
||||
app := application.New(application.Options{
|
||||
app = application.New(application.Options{
|
||||
Name: "Key Bindings Demo",
|
||||
Description: "A demo of the Key Bindings Options",
|
||||
Mac: application.MacOptions{
|
||||
|
|
@ -15,7 +17,7 @@ func main() {
|
|||
},
|
||||
KeyBindings: map[string]func(window application.Window){
|
||||
"shift+ctrl+c": func(window application.Window) {
|
||||
selection, err := application.OpenFileDialog().
|
||||
selection, err := app.Dialog.OpenFile().
|
||||
CanChooseFiles(true).
|
||||
CanCreateDirectories(true).
|
||||
ShowHiddenFiles(true).
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func main() {
|
|||
})
|
||||
|
||||
window.OnWindowEvent(events.Common.WindowShow, func(event *application.WindowEvent) {
|
||||
application.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("File Opened").
|
||||
SetMessage("Application opened with file: " + filename).
|
||||
Show()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
|
@ -25,10 +26,11 @@ func main() {
|
|||
// Check if running on macOS
|
||||
if runtime.GOOS != "darwin" {
|
||||
// Show dialog for non-macOS platforms
|
||||
application.InfoDialog().
|
||||
app.Dialog.Info().
|
||||
SetTitle("macOS Only Demo").
|
||||
SetMessage("The Liquid Glass effect is a macOS-specific feature that uses native NSGlassEffectView (macOS 15.0+) or NSVisualEffectView.\n\nThis demo is not available on " + runtime.GOOS + ".").
|
||||
Show()
|
||||
fmt.Println("The Liquid Glass effect is a macOS-specific feature. This demo is not available on", runtime.GOOS)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import (
|
|||
//go:embed assets/*
|
||||
var assets embed.FS
|
||||
|
||||
var app *application.App
|
||||
|
||||
type WindowService struct{}
|
||||
|
||||
func (s *WindowService) GeneratePanic() {
|
||||
|
|
@ -27,7 +29,7 @@ func (s *WindowService) call2() {
|
|||
// ==============================================
|
||||
|
||||
func main() {
|
||||
app := application.New(application.Options{
|
||||
app = application.New(application.Options{
|
||||
Name: "Panic Handler Demo",
|
||||
Description: "A demo of Handling Panics",
|
||||
Assets: application.AssetOptions{
|
||||
|
|
@ -44,7 +46,7 @@ func main() {
|
|||
fmt.Printf("Time: %s\n", panicDetails.Time)
|
||||
fmt.Printf("Error: %s\n", panicDetails.Error)
|
||||
fmt.Printf("Stacktrace: %s\n", panicDetails.StackTrace)
|
||||
application.InfoDialog().SetMessage("There was a panic!").Show()
|
||||
app.Dialog.Info().SetMessage("There was a panic!").Show()
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ func main() {
|
|||
|
||||
myMenu.Add("Hello World!").OnClick(func(ctx *application.Context) {
|
||||
println("Hello World!")
|
||||
q := application.QuestionDialog().SetTitle("Ready?").SetMessage("Are you feeling ready?")
|
||||
q := app.Dialog.Question().SetTitle("Ready?").SetMessage("Are you feeling ready?")
|
||||
q.AddButton("Yes").OnClick(func() {
|
||||
println("Awesome!")
|
||||
})
|
||||
|
|
@ -75,7 +75,7 @@ func main() {
|
|||
myMenu.AddSeparator()
|
||||
myMenu.AddCheckbox("Checked", true).OnClick(func(ctx *application.Context) {
|
||||
println("Checked: ", ctx.ClickedMenuItem().Checked())
|
||||
application.InfoDialog().SetTitle("Hello World!").SetMessage("Hello World!").Show()
|
||||
app.Dialog.Info().SetTitle("Hello World!").SetMessage("Hello World!").Show()
|
||||
})
|
||||
myMenu.Add("Enabled").OnClick(func(ctx *application.Context) {
|
||||
println("Click me!")
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ func main() {
|
|||
sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
width, height := w.Size()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -544,7 +544,7 @@ func main() {
|
|||
positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
x, y := w.Position()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -568,7 +568,7 @@ func main() {
|
|||
positionMenu.Add("Get Relative Position").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
x, y := w.RelativePosition()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -681,24 +681,24 @@ func main() {
|
|||
stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) {
|
||||
screen := app.Screen.GetPrimary()
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
})
|
||||
stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) {
|
||||
screens := app.Screen.GetAll()
|
||||
for _, screen := range screens {
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
}
|
||||
})
|
||||
stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
screen, err := w.GetScreen()
|
||||
if err != nil {
|
||||
application.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
})
|
||||
})
|
||||
stateMenu.Add("Disable for 5s").OnClick(func(ctx *application.Context) {
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ func main() {
|
|||
sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
width, height := w.Size()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ func main() {
|
|||
positionMenu.Add("Get Relative Position").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
x, y := w.RelativePosition()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ func main() {
|
|||
positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
x, y := w.Position()
|
||||
application.InfoDialog().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show()
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -342,24 +342,24 @@ func main() {
|
|||
stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) {
|
||||
screen := app.Screen.GetPrimary()
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle("Primary Screen").SetMessage(msg).Show()
|
||||
})
|
||||
stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) {
|
||||
screens := app.Screen.GetAll()
|
||||
for _, screen := range screens {
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
}
|
||||
})
|
||||
stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) {
|
||||
currentWindow(func(w application.Window) {
|
||||
screen, err := w.GetScreen()
|
||||
if err != nil {
|
||||
application.ErrorDialog().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show()
|
||||
return
|
||||
}
|
||||
msg := fmt.Sprintf("Screen: %+v", screen)
|
||||
application.InfoDialog().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show()
|
||||
})
|
||||
})
|
||||
stateMenu.Add("Disable for 5s").OnClick(func(ctx *application.Context) {
|
||||
|
|
|
|||
|
|
@ -863,30 +863,6 @@ func (a *App) SetIcon(icon []byte) {
|
|||
}
|
||||
}
|
||||
|
||||
func InfoDialog() *MessageDialog {
|
||||
return newMessageDialog(InfoDialogType)
|
||||
}
|
||||
|
||||
func QuestionDialog() *MessageDialog {
|
||||
return newMessageDialog(QuestionDialogType)
|
||||
}
|
||||
|
||||
func WarningDialog() *MessageDialog {
|
||||
return newMessageDialog(WarningDialogType)
|
||||
}
|
||||
|
||||
func ErrorDialog() *MessageDialog {
|
||||
return newMessageDialog(ErrorDialogType)
|
||||
}
|
||||
|
||||
func OpenFileDialog() *OpenFileDialogStruct {
|
||||
return newOpenFileDialog()
|
||||
}
|
||||
|
||||
func SaveFileDialog() *SaveFileDialogStruct {
|
||||
return newSaveFileDialog()
|
||||
}
|
||||
|
||||
func (a *App) dispatchOnMainThread(fn func()) {
|
||||
// If we are on the main thread, just call the function
|
||||
if a.impl.isOnMainThread() {
|
||||
|
|
|
|||
|
|
@ -14,44 +14,44 @@ func newDialogManager(app *App) *DialogManager {
|
|||
|
||||
// OpenFile creates a file dialog for selecting files
|
||||
func (dm *DialogManager) OpenFile() *OpenFileDialogStruct {
|
||||
return OpenFileDialog()
|
||||
return newOpenFileDialog()
|
||||
}
|
||||
|
||||
// OpenFileWithOptions creates a file dialog with options
|
||||
func (dm *DialogManager) OpenFileWithOptions(options *OpenFileDialogOptions) *OpenFileDialogStruct {
|
||||
result := OpenFileDialog()
|
||||
result := newOpenFileDialog()
|
||||
result.SetOptions(options)
|
||||
return result
|
||||
}
|
||||
|
||||
// SaveFile creates a save file dialog
|
||||
func (dm *DialogManager) SaveFile() *SaveFileDialogStruct {
|
||||
return SaveFileDialog()
|
||||
return newSaveFileDialog()
|
||||
}
|
||||
|
||||
// SaveFileWithOptions creates a save file dialog with options
|
||||
func (dm *DialogManager) SaveFileWithOptions(options *SaveFileDialogOptions) *SaveFileDialogStruct {
|
||||
result := SaveFileDialog()
|
||||
result := newSaveFileDialog()
|
||||
result.SetOptions(options)
|
||||
return result
|
||||
}
|
||||
|
||||
// Info creates an information dialog
|
||||
func (dm *DialogManager) Info() *MessageDialog {
|
||||
return InfoDialog()
|
||||
return newMessageDialog(InfoDialogType)
|
||||
}
|
||||
|
||||
// Question creates a question dialog
|
||||
func (dm *DialogManager) Question() *MessageDialog {
|
||||
return QuestionDialog()
|
||||
return newMessageDialog(QuestionDialogType)
|
||||
}
|
||||
|
||||
// Warning creates a warning dialog
|
||||
func (dm *DialogManager) Warning() *MessageDialog {
|
||||
return WarningDialog()
|
||||
return newMessageDialog(WarningDialogType)
|
||||
}
|
||||
|
||||
// Error creates an error dialog
|
||||
func (dm *DialogManager) Error() *MessageDialog {
|
||||
return ErrorDialog()
|
||||
return newMessageDialog(ErrorDialogType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ func (m *MessageProcessor) processDialogMethod(req *RuntimeRequest, window Windo
|
|||
var dialog *MessageDialog
|
||||
switch req.Method {
|
||||
case DialogInfo:
|
||||
dialog = InfoDialog()
|
||||
dialog = newMessageDialog(InfoDialogType)
|
||||
case DialogWarning:
|
||||
dialog = WarningDialog()
|
||||
dialog = newMessageDialog(WarningDialogType)
|
||||
case DialogError:
|
||||
dialog = ErrorDialog()
|
||||
dialog = newMessageDialog(ErrorDialogType)
|
||||
case DialogQuestion:
|
||||
dialog = QuestionDialog()
|
||||
dialog = newMessageDialog(QuestionDialogType)
|
||||
}
|
||||
var detached = args.Bool("Detached")
|
||||
if detached == nil || !*detached {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue