🎯 Рекомендуемые коллекции
Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать
Примеры Desktop Функций Web Go
Примеры desktop-специфичных функций Web Go включая файловые диалоги, messagebox'ы и системный трей
💻 MessageBox'ы go
🟢 simple
⭐⭐⭐
Показывать информационные, предупреждающие и ошибочные messagebox'ы
⏱️ 20 min
🏷️ go, web, desktop features
Prerequisites:
Basic Go, GUI framework
// Web Go Message Box Examples
// Using Fyne and Walk for message dialogs
package main
import (
"fmt"
"os"
)
// 1. Using Fyne Framework
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/dialog"
)
func FyneInfoDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Message Dialog")
dialog.ShowInformation("Information", "This is an info message", myWindow)
myWindow.ShowAndRun()
}
func FyneErrorDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Error Dialog")
dialog.ShowError(errors.New("This is an error message"), myWindow)
myWindow.ShowAndRun()
}
func FyneConfirmDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Confirm Dialog")
dialog.ShowConfirm("Confirm", "Are you sure?", func(confirmed bool) {
if confirmed {
fmt.Println("User confirmed")
} else {
fmt.Println("User cancelled")
}
}, myWindow)
myWindow.ShowAndRun()
}
*/
// 2. Using Walk Framework (Windows)
/*
import (
"github.com/lxn/walk"
)
func WalkMessageBox() error {
// Information
walk.MsgBox(nil, "Information",
"This is an info message",
walk.MsgBoxIconInformation)
// Warning
walk.MsgBox(nil, "Warning",
"This is a warning",
walk.MsgBoxIconWarning)
// Error
walk.MsgBox(nil, "Error",
"This is an error",
walk.MsgBoxIconError)
// Question with Yes/No
ret, err := walk.MsgBox(nil, "Question",
"Do you want to continue?",
walk.MsgBoxYesNo|walk.MsgBoxIconQuestion)
if err == nil {
if ret == walk.DialogButtonYes {
fmt.Println("User clicked Yes")
} else {
fmt.Println("User clicked No")
}
}
return nil
}
*/
// 3. Cross-Platform Message Box
// MessageType defines message box type
type MessageType int
const (
InfoMsg MessageType = iota
WarningMsg
ErrorMsg
QuestionMsg
)
// MessageBoxButton defines button type
type MessageBoxButton int
const (
OKBtn MessageBoxButton = iota
OKCancelBtn
YesNoBtn
YesNoCancelBtn
RetryCancelBtn
AbortRetryIgnoreBtn
)
// MessageBoxResult holds message box result
type MessageBoxResult struct {
ButtonPressed string
Confirmed bool
Err error
}
// MessageBox shows message box
func MessageBox(title, message string, msgType MessageType, buttons MessageBoxButton) MessageBoxResult {
// Terminal-based message box
return showTerminalMessageBox(title, message, msgType, buttons)
}
func showTerminalMessageBox(title, message string, msgType MessageType, buttons MessageBoxButton) MessageBoxResult {
// Print message header
var icon string
switch msgType {
case InfoMsg:
icon = "ℹ️"
case WarningMsg:
icon = "⚠️"
case ErrorMsg:
icon = "❌"
case QuestionMsg:
icon = "❓"
}
fmt.Printf("\n%s %s\n", icon, title)
fmt.Printf("%s\n", message)
// Print buttons
var options []string
switch buttons {
case OKBtn:
options = []string{"OK"}
case OKCancelBtn:
options = []string{"OK", "Cancel"}
case YesNoBtn:
options = []string{"Yes", "No"}
case YesNoCancelBtn:
options = []string{"Yes", "No", "Cancel"}
case RetryCancelBtn:
options = []string{"Retry", "Cancel"}
case AbortRetryIgnoreBtn:
options = []string{"Abort", "Retry", "Ignore"}
}
fmt.Print("Options: ")
for i, opt := range options {
if i > 0 {
fmt.Print(", ")
}
fmt.Printf("[%d] %s", i+1, opt)
}
fmt.Println()
// Get user input
var choice int
fmt.Scanln(&choice)
if choice < 1 || choice > len(options) {
return MessageBoxResult{Err: fmt.Errorf("invalid choice")}
}
selected := options[choice-1]
return MessageBoxResult{
ButtonPressed: selected,
Confirmed: selected == "OK" || selected == "Yes" || selected == "Retry",
}
}
// 4. Convenience Functions
// ShowInfo shows information message
func ShowInfo(title, message string) MessageBoxResult {
return MessageBox(title, message, InfoMsg, OKBtn)
}
// ShowWarning shows warning message
func ShowWarning(title, message string) MessageBoxResult {
return MessageBox(title, message, WarningMsg, OKBtn)
}
// ShowError shows error message
func ShowError(title, message string) MessageBoxResult {
return MessageBox(title, message, ErrorMsg, OKBtn)
}
// ShowQuestion shows question with Yes/No
func ShowQuestion(title, message string) MessageBoxResult {
result := MessageBox(title, message, QuestionMsg, YesNoBtn)
return result
}
// ShowConfirm shows confirmation dialog
func ShowConfirm(title, message string) MessageBoxResult {
result := MessageBox(title, message, QuestionMsg, OKCancelBtn)
return result
}
// 5. Progress Dialog
// ProgressDialog shows progress for operations
type ProgressDialog struct {
title string
total int64
current int64
cancelled bool
}
// NewProgressDialog creates progress dialog
func NewProgressDialog(title string, total int64) *ProgressDialog {
return &ProgressDialog{
title: title,
total: total,
current: 0,
}
}
// Update updates progress
func (pd *ProgressDialog) Update(current int64) {
pd.current = current
// Clear line and show progress
fmt.Printf("\r%s: ", pd.title)
percentage := float64(current) / float64(pd.total) * 100
barWidth := 40
filled := int(float64(barWidth) * float64(current) / float64(pd.total))
fmt.Print("[")
for i := 0; i < barWidth; i++ {
if i < filled {
fmt.Print("=")
} else {
fmt.Print(" ")
}
}
fmt.Printf("] %.1f%%", percentage)
}
// Complete marks progress as complete
func (pd *ProgressDialog) Complete() {
pd.Update(pd.total)
fmt.Println(" - Complete!")
}
// 6. Notification
// NotificationType defines notification type
type NotificationType int
const (
NotificationInfo NotificationType = iota
NotificationWarning
NotificationError
NotificationSuccess
)
// ShowNotification shows desktop notification
func ShowNotification(title, message string, notifType NotificationType) {
// Terminal notification
var icon string
switch notifType {
case NotificationInfo:
icon = "ℹ️"
case NotificationWarning:
icon = "⚠️"
case NotificationError:
icon = "❌"
case NotificationSuccess:
icon = "✅"
}
fmt.Printf("\n%s %s: %s\n", icon, title, message)
}
// 7. Input Dialog
// InputDialogResult holds input dialog result
type InputDialogResult struct {
Value string
Err error
}
// ShowInputDialog shows input dialog
func ShowInputDialog(title, prompt, defaultValue string) InputDialogResult {
fmt.Printf("\n%s\n", title)
fmt.Printf("%s", prompt)
if defaultValue != "" {
fmt.Printf(" [%s]", defaultValue)
}
fmt.Print(": ")
var input string
fmt.Scanln(&input)
if input == "" {
input = defaultValue
}
return InputDialogResult{Value: input}
}
// ShowPasswordDialog shows password input dialog
func ShowPasswordDialog(title, prompt string) InputDialogResult {
fmt.Printf("\n%s\n", title)
fmt.Printf("%s: ", prompt)
// Note: In terminal, password won't be hidden
// For real applications, use terminal password reading
var input string
fmt.Scanln(&input)
return InputDialogResult{Value: input}
}
// 8. Select Dialog
// SelectDialogResult holds selection dialog result
type SelectDialogResult struct {
SelectedIndex int
SelectedValue string
Err error
}
// ShowSelectDialog shows selection dialog
func ShowSelectDialog(title string, options []string) SelectDialogResult {
fmt.Printf("\n%s\n", title)
for i, opt := range options {
fmt.Printf("[%d] %s\n", i+1, opt)
}
fmt.Print("Select: ")
var choice int
fmt.Scanln(&choice)
if choice < 1 || choice > len(options) {
return SelectDialogResult{Err: fmt.Errorf("invalid choice")}
}
return SelectDialogResult{
SelectedIndex: choice - 1,
SelectedValue: options[choice-1],
}
}
// 9. Dialog Builder
// DialogBuilder builds message dialogs
type DialogBuilder struct {
title string
message string
msgType MessageType
buttons MessageBoxButton
onConfirm func()
onCancel func()
defaultAction func()
}
// NewDialogBuilder creates dialog builder
func NewDialogBuilder(title, message string) *DialogBuilder {
return &DialogBuilder{
title: title,
message: message,
msgType: InfoMsg,
buttons: OKBtn,
}
}
func (db *DialogBuilder) WithType(msgType MessageType) *DialogBuilder {
db.msgType = msgType
return db
}
func (db *DialogBuilder) WithButtons(buttons MessageBoxButton) *DialogBuilder {
db.buttons = buttons
return db
}
func (db *DialogBuilder) OnConfirm(fn func()) *DialogBuilder {
db.onConfirm = fn
return db
}
func (db *DialogBuilder) OnCancel(fn func()) *DialogBuilder {
db.onCancel = fn
return db
}
func (db *DialogBuilder) Show() MessageBoxResult {
result := MessageBox(db.title, db.message, db.msgType, db.buttons)
if result.Confirmed && db.onConfirm != nil {
db.onConfirm()
} else if !result.Confirmed && db.onCancel != nil {
db.onCancel()
}
return result
}
// Usage Examples
func main() {
fmt.Println("=== Web Go Message Box Examples ===\n")
// 1. Info message
fmt.Println("--- 1. Info Message ---")
ShowInfo("Information", "This is an informational message")
// 2. Warning message
fmt.Println("\n--- 2. Warning Message ---")
ShowWarning("Warning", "This is a warning message")
// 3. Error message
fmt.Println("\n--- 3. Error Message ---")
ShowError("Error", "An error occurred!")
// 4. Question dialog
fmt.Println("\n--- 4. Question Dialog ---")
result := ShowQuestion("Question", "Do you want to continue?")
if result.Confirmed {
fmt.Println("User chose Yes")
} else {
fmt.Println("User chose No")
}
// 5. Input dialog
fmt.Println("\n--- 5. Input Dialog ---")
input := ShowInputDialog("Name", "Enter your name", "")
if input.Err == nil {
fmt.Printf("Hello, %s!\n", input.Value)
}
// 6. Select dialog
fmt.Println("\n--- 6. Select Dialog ---")
selectResult := ShowSelectDialog("Choose Option", []string{"Option A", "Option B", "Option C"})
if selectResult.Err == nil {
fmt.Printf("Selected: %s\n", selectResult.SelectedValue)
}
// 7. Progress dialog
fmt.Println("\n--- 7. Progress Dialog ---")
progress := NewProgressDialog("Processing", 100)
for i := 0; i <= 100; i += 10 {
progress.Update(int64(i))
time.Sleep(100 * time.Millisecond)
}
progress.Complete()
// 8. Notification
fmt.Println("
--- 8. Notification ---")
ShowNotification("Success", "Operation completed successfully!", NotificationSuccess)
// 9. Dialog builder
fmt.Println("
--- 9. Dialog Builder ---")
builderResult := NewDialogBuilder("Confirm Action", "Are you sure?").
WithType(QuestionMsg).
WithButtons(YesNoBtn).
OnConfirm(func() {
fmt.Println("Action confirmed!")
}).
Show()
fmt.Printf("
Builder result: %v\n", builderResult.ButtonPressed)
fmt.Println("
=== All Message Box Examples Completed ===")
fmt.Println("Note: For full GUI functionality, install Fyne or Walk framework")
}
💻 Файловые Диалоги go
🟡 intermediate
⭐⭐⭐
Открывать и сохранять файловые диалоги используя GUI фреймворки Fyne или Walk
⏱️ 30 min
🏷️ go, web, desktop features
Prerequisites:
Intermediate Go, GUI framework
// Web Go File Dialog Examples
// Using Fyne and Walk frameworks for file dialogs
package main
import (
"fmt"
"os"
"path/filepath"
)
// 1. Using Fyne Framework (Cross-platform)
// FyneFileDialogExample demonstrates file dialogs with Fyne
// Install: go get fyne.io/fyne/v2
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
)
func FyneOpenFileDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("File Dialog")
// Create open file dialog
fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
if err == nil && reader != nil {
defer reader.Close()
fmt.Printf("Opened file: %v\n", reader.URI())
}
}, myWindow)
fd.SetFilter(storage.NewExtensionFileFilter([]string{".txt", ".go"}))
fd.Show()
// Keep window running
myWindow.ShowAndRun()
}
func FyneSaveFileDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Save Dialog")
// Create save file dialog
sd := dialog.NewFileSave(func(writer fyne.URIWriteCloser, err error) {
if err == nil && writer != nil {
defer writer.Close()
writer.Write([]byte("Hello, World!"))
fmt.Printf("Saved file: %v\n", writer.URI())
}
}, myWindow)
sd.SetFileName("untitled.txt")
sd.Show()
myWindow.ShowAndRun()
}
func FyneSelectFolderDialog() {
myApp := app.New()
myWindow := myApp.NewWindow("Folder Dialog")
// Create folder select dialog
fd := dialog.NewFolderOpen(func(uri fyne.ListableURI, err error) {
if err == nil && uri != nil {
fmt.Printf("Selected folder: %v\n", uri)
}
}, myWindow)
fd.Show()
myWindow.ShowAndRun()
}
*/
// 2. Using Walk Framework (Windows)
// WalkFileDialogExample demonstrates file dialogs with Walk
// Install: go get github.com/lxn/walk
/*
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
func WalkOpenFileDialog() {
var dlg *walk.Dialog
var text *walk.TextEdit
MainWindow{
Title: "File Dialog",
MinSize: Size{400, 300},
Layout: VBox{},
Children: []Widget{
PushButton{
Text: "Open File",
OnClicked: func() {
filePath, err := walk.FileDialog{
Filter: "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
Title: "Open File",
}.ShowOpen(nil)
if err == nil && filePath != "" {
text.SetText(filePath)
fmt.Printf("Opened: %s\n", filePath)
}
},
},
TextEdit{AssignTo: &text},
},
}.Create()
}
func WalkSaveFileDialog() {
var fileName *walk.LineEdit
MainWindow{
Title: "Save Dialog",
Layout: VBox{},
Children: []Widget{
PushButton{
Text: "Save File",
OnClicked: func() {
filePath, err := walk.FileDialog{
Filter: "Text Files (*.txt)|*.txt",
Title: "Save File",
}.ShowSave(nil)
if err == nil && filePath != "" {
fmt.Printf("Save to: %s\n", filePath)
}
},
},
LineEdit{AssignTo: &fileName},
},
}.Create()
}
*/
// 3. Cross-Platform File Dialog Wrapper
// FileDialogOptions holds options for file dialogs
type FileDialogOptions struct {
Title string
Filter string
InitialDir string
DefaultName string
}
// FileDialogResult holds file dialog result
type FileDialogResult struct {
FilePath string
FileName string
Dir string
Err error
}
// OpenFileDialog opens file selection dialog
func OpenFileDialog(options FileDialogOptions) FileDialogResult {
result := FileDialogResult{}
// Check if running in terminal environment
if os.Getenv("TERM") != "" || os.Getenv("TERM_PROGRAM") != "" {
// Terminal-based file selection
return openTerminalFileDialog(options)
}
// Try GUI frameworks
// Note: In a real application, you'd use Fyne or Walk here
result.Err = fmt.Errorf("no GUI framework available")
return result
}
// SaveFileDialog opens save file dialog
func SaveFileDialog(options FileDialogOptions) FileDialogResult {
result := FileDialogResult{}
// Check environment
if os.Getenv("TERM") != "" {
return saveTerminalFileDialog(options)
}
result.Err = fmt.Errorf("no GUI framework available")
return result
}
// 4. Terminal-Based File Dialog (Fallback)
func openTerminalFileDialog(options FileDialogOptions) FileDialogResult {
fmt.Printf("%s\n", options.Title)
fmt.Println("Enter file path (or 'cancel'): ")
var input string
fmt.Scanln(&input)
if input == "cancel" {
return FileDialogResult{Err: fmt.Errorf("cancelled")}
}
if _, err := os.Stat(input); err != nil {
return FileDialogResult{Err: err}
}
return FileDialogResult{
FilePath: input,
FileName: filepath.Base(input),
Dir: filepath.Dir(input),
}
}
func saveTerminalFileDialog(options FileDialogOptions) FileDialogResult {
fmt.Printf("%s\n", options.Title)
defaultName := options.DefaultName
if defaultName == "" {
defaultName = "untitled.txt"
}
fmt.Printf("Enter save path [%s]: ", defaultName)
var input string
fmt.Scanln(&input)
if input == "" {
input = defaultName
}
return FileDialogResult{
FilePath: input,
FileName: filepath.Base(input),
Dir: filepath.Dir(input),
}
}
// 5. File Dialog with Validation
// OpenFileDialogWithValidation opens dialog and validates file
func OpenFileDialogWithValidation(options FileDialogOptions, validateFunc func(string) error) FileDialogResult {
result := OpenFileDialog(options)
if result.Err != nil {
return result
}
if validateFunc != nil {
if err := validateFunc(result.FilePath); err != nil {
return FileDialogResult{Err: err}
}
}
return result
}
// ValidateFileExtension validates file extension
func ValidateFileExtension(extensions []string) func(string) error {
return func(filePath string) error {
ext := filepath.Ext(filePath)
for _, validExt := range extensions {
if ext == validExt {
return nil
}
}
return fmt.Errorf("invalid extension: %s", ext)
}
}
// ValidateFileSize validates file size
func ValidateFileSize(maxSizeMB int64) func(string) error {
return func(filePath string) error {
info, err := os.Stat(filePath)
if err != nil {
return err
}
sizeMB := info.Size() / (1024 * 1024)
if sizeMB > maxSizeMB {
return fmt.Errorf("file too large: %dMB (max %dMB)", sizeMB, maxSizeMB)
}
return nil
}
}
// 6. Batch File Selection
// BatchFileDialogResult holds multiple file selection results
type BatchFileDialogResult struct {
FilePaths []string
Err error
}
// OpenMultipleFilesDialog opens dialog for multiple file selection
func OpenMultipleFilesDialog(options FileDialogOptions) BatchFileDialogResult {
result := BatchFileDialogResult{}
fmt.Printf("%s (Multiple files)\n", options.Title)
fmt.Println("Enter file paths (one per line, empty line to finish):")
var filePaths []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
path := scanner.Text()
if path == "" {
break
}
filePaths = append(filePaths, path)
}
if len(filePaths) == 0 {
result.Err = fmt.Errorf("no files selected")
return result
}
// Validate all files
for _, path := range filePaths {
if _, err := os.Stat(path); err != nil {
result.Err = fmt.Errorf("invalid file: %s - %v", path, err)
return result
}
}
result.FilePaths = filePaths
return result
}
// 7. Recent Files Management
// RecentFiles manages recent file list
type RecentFiles struct {
files []string
max int
}
// NewRecentFiles creates recent files manager
func NewRecentFiles(maxFiles int) *RecentFiles {
return &RecentFiles{
files: []string{},
max: maxFiles,
}
}
// Add adds file to recent list
func (rf *RecentFiles) Add(filePath string) {
// Remove if already exists
for i, f := range rf.files {
if f == filePath {
rf.files = append(rf.files[:i], rf.files[i+1:]...)
break
}
}
// Add to front
rf.files = append([]string{filePath}, rf.files...)
// Limit size
if len(rf.files) > rf.max {
rf.files = rf.files[:rf.max]
}
}
// GetFiles returns recent files list
func (rf *RecentFiles) GetFiles() []string {
return rf.files
}
// SaveToFile saves recent files to file
func (rf *RecentFiles) SaveToFile(filePath string) error {
file, err := os.Create(filePath)
if err != nil {
return err
}
defer file.Close()
for _, f := range rf.files {
file.WriteString(f + "\n")
}
return nil
}
// LoadFromFile loads recent files from file
func (rf *RecentFiles) LoadFromFile(filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
rf.Add(scanner.Text())
}
return scanner.Err()
}
// 8. File Dialog Presets
// OpenImageDialog opens image file dialog
func OpenImageDialog() FileDialogResult {
return OpenFileDialog(FileDialogOptions{
Title: "Open Image",
Filter: "*.png;*.jpg;*.jpeg;*.gif;*.bmp",
})
}
// SaveTextFileDialog opens text file save dialog
func SaveTextFileDialog() FileDialogResult {
return SaveFileDialog(FileDialogOptions{
Title: "Save Text File",
Filter: "*.txt",
DefaultName: "untitled.txt",
})
}
// OpenCodeFileDialog opens code file dialog
func OpenCodeFileDialog() FileDialogResult {
return OpenFileDialog(FileDialogOptions{
Title: "Open Code File",
Filter: "*.go;*.js;*.py;*.java;*.cpp",
})
}
// Usage Examples
func main() {
fmt.Println("=== Web Go File Dialog Examples ===\n")
// 1. Open file dialog
fmt.Println("--- 1. Open File Dialog ---")
result := OpenFileDialog(FileDialogOptions{
Title: "Select a File",
Filter: "*.txt",
})
if result.Err == nil {
fmt.Printf("Selected: %s\n", result.FilePath)
}
// 2. Save file dialog
fmt.Println("\n--- 2. Save File Dialog ---")
saveResult := SaveFileDialog(FileDialogOptions{
Title: "Save File",
DefaultName: "output.txt",
})
if saveResult.Err == nil {
fmt.Printf("Save to: %s\n", saveResult.FilePath)
}
// 3. File dialog with validation
fmt.Println("\n--- 3. File Dialog with Validation ---")
validated := OpenFileDialogWithValidation(
FileDialogOptions{Title: "Select Text File"},
ValidateFileExtension([]string{".txt"}),
)
if validated.Err != nil {
fmt.Printf("Validation error: %v\n", validated.Err)
}
// 4. Multiple files
fmt.Println("\n--- 4. Multiple Files ---")
multi := OpenMultipleFilesDialog(FileDialogOptions{
Title: "Select Files",
})
if multi.Err == nil {
fmt.Printf("Selected %d files\n", len(multi.FilePaths))
}
// 5. Recent files
fmt.Println("\n--- 5. Recent Files ---")
recent := NewRecentFiles(5)
recent.Add("file1.txt")
recent.Add("file2.txt")
recent.Add("file3.txt")
fmt.Printf("Recent files: %v\n", recent.GetFiles())
// 6. Presets
fmt.Println("\n--- 6. Preset Dialogs ---")
imageResult := OpenImageDialog()
if imageResult.Err == nil {
fmt.Printf("Image: %s\n", imageResult.FileName)
}
fmt.Println("\n=== All File Dialog Examples Completed ===")
fmt.Println("Note: For full GUI functionality, install Fyne or Walk framework")
}
💻 Системный Трей go
🔴 complex
⭐⭐⭐⭐
Показывать иконку системного трея с меню и уведомлениями
⏱️ 30 min
🏷️ go, web, desktop features
Prerequisites:
Intermediate Go, GUI framework, goroutines
// Web Go System Tray Examples
// System tray icon with menu using Fyne or other frameworks
package main
import (
"fmt"
"os"
"time"
)
// 1. Using Fyne Framework
/*
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/menu"
"fyne.io/fyne/v2/storage"
)
func FyneSystemTray() {
myApp := app.New()
myWindow := myApp.NewWindow("System Tray")
// Create system tray
if desk, ok := myApp.(desktop.App); ok {
// Set system tray icon
icon := storage.NewFileURI("icon.png")
desk.SetSystemTrayIcon(icon)
desk.SetSystemTrayMenu(menu.New(
menu.NewItem("Show", func() { myWindow.Show() }),
menu.NewItem("Hide", func() { myWindow.Hide() }),
menu.NewSeparator(),
menu.NewItem("Quit", func() { myApp.Quit() }),
))
}
myWindow.ShowAndRun()
}
*/
// 2. Using Systray Framework (Cross-platform)
/*
import (
"github.com/getlantern/systray"
)
func SystrayExample() {
systray.Run(onReady, onExit)
}
func onReady() {
// Set icon
// iconBytes, _ := ioutil.ReadFile("icon.ico")
// systray.SetIcon(iconBytes)
systray.SetTitle("My App")
systray.SetTooltip("My Application")
// Add menu items
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
mShow := systray.AddMenuItem("Show", "Show window")
mHide := systray.AddMenuItem("Hide", "Hide window")
// Handle menu clicks
go func() {
for {
select {
case <-mShow.ClickedCh:
fmt.Println("Show clicked")
case <-mHide.ClickedCh:
fmt.Println("Hide clicked")
case <-mQuit.ClickedCh:
fmt.Println("Quitting...")
systray.Quit()
return
}
}
}()
}
func onExit() {
fmt.Println("Exiting systray")
}
*/
// 3. Simulated System Tray (Terminal)
// TrayIcon represents a system tray icon
type TrayIcon struct {
title string
tooltip string
menuItems []TrayMenuItem
visible bool
running bool
onQuit func()
notification string
}
// TrayMenuItem represents a menu item
type TrayMenuItem struct {
Title string
Tooltip string
Disabled bool
OnClick func()
}
// NewTrayIcon creates new tray icon
func NewTrayIcon(title, tooltip string) *TrayIcon {
return &TrayIcon{
title: title,
tooltip: tooltip,
menuItems: []TrayMenuItem{},
visible: false,
running: false,
}
}
// SetTitle sets tray icon title
func (ti *TrayIcon) SetTitle(title string) {
ti.title = title
fmt.Printf("[Tray] Title set to: %s\n", title)
}
// SetTooltip sets tooltip
func (ti *TrayIcon) SetTooltip(tooltip string) {
ti.tooltip = tooltip
fmt.Printf("[Tray] Tooltip set to: %s\n", tooltip)
}
// AddMenuItem adds menu item
func (ti *TrayIcon) AddMenuItem(title, tooltip string, onClick func()) {
item := TrayMenuItem{
Title: title,
Tooltip: tooltip,
OnClick: onClick,
}
ti.menuItems = append(ti.menuItems, item)
fmt.Printf("[Tray] Menu item added: %s\n", title)
}
// AddSeparator adds separator
func (ti *TrayIcon) AddSeparator() {
fmt.Println("[Tray] Separator added")
}
// Show shows tray icon
func (ti *TrayIcon) Show() {
ti.visible = true
ti.running = true
fmt.Printf("[Tray] Icon shown: %s\n", ti.title)
ti.run()
}
// Hide hides tray icon
func (ti *TrayIcon) Hide() {
ti.visible = false
fmt.Println("[Tray] Icon hidden")
}
// Quit quits tray icon
func (ti *TrayIcon) Quit() {
ti.running = false
if ti.onQuit != nil {
ti.onQuit()
}
fmt.Println("[Tray] Quit")
}
// OnQuit sets quit handler
func (ti *TrayIcon) OnQuit(fn func()) {
ti.onQuit = fn
}
// ShowNotification shows notification
func (ti *TrayIcon) ShowNotification(title, message string) {
ti.notification = fmt.Sprintf("%s: %s", title, message)
fmt.Printf("[Tray] Notification: %s\n", ti.notification)
}
// run runs tray icon loop
func (ti *TrayIcon) run() {
fmt.Println("[Tray] Running... (Press Ctrl+C to quit)")
fmt.Println("Menu items:")
for i, item := range ti.menuItems {
fmt.Printf(" [%d] %s\n", i+1, item.Title)
}
// Simple menu loop
for ti.running {
time.Sleep(100 * time.Millisecond)
}
}
// 4. Tray Menu Manager
// TrayMenu manages tray menu
type TrayMenu struct {
items []TrayMenuItem
}
// NewTrayMenu creates tray menu
func NewTrayMenu() *TrayMenu {
return &TrayMenu{
items: []TrayMenuItem{},
}
}
// AddItem adds menu item
func (tm *TrayMenu) AddItem(title, tooltip string, onClick func()) {
tm.items = append(tm.items, TrayMenuItem{
Title: title,
Tooltip: tooltip,
OnClick: onClick,
})
}
// AddSubmenu adds submenu
func (tm *TrayMenu) AddSubmenu(title string) *TrayMenu {
submenu := &TrayMenu{}
fmt.Printf("[Tray] Submenu added: %s\n", title)
return submenu
}
// AddSeparator adds separator
func (tm *TrayMenu) AddSeparator() {
fmt.Println("[Tray] Separator added")
}
// 5. Tray Application
// TrayApp represents a complete tray application
type TrayApp struct {
tray *TrayIcon
menu *TrayMenu
running bool
}
// NewTrayApp creates new tray application
func NewTrayApp(title, tooltip string) *TrayApp {
tray := NewTrayIcon(title, tooltip)
return &TrayApp{
tray: tray,
menu: NewTrayMenu(),
running: false,
}
}
// AddMenuItem adds menu item
func (ta *TrayApp) AddMenuItem(title, tooltip string, onClick func()) {
ta.tray.AddMenuItem(title, tooltip, onClick)
}
// AddSeparator adds separator
func (ta *TrayApp) AddSeparator() {
ta.tray.AddSeparator()
}
// SetOnQuit sets quit handler
func (ta *TrayApp) SetOnQuit(fn func()) {
ta.tray.OnQuit(fn)
}
// Run runs tray application
func (ta *TrayApp) Run() {
ta.running = true
ta.tray.Show()
}
// ShowNotification shows notification
func (ta *TrayApp) ShowNotification(title, message string) {
ta.tray.ShowNotification(title, message)
}
// Quit quits application
func (ta *TrayApp) Quit() {
ta.running = false
ta.tray.Quit()
}
// 6. Tray Builder
// TrayBuilder builds tray applications
type TrayBuilder struct {
app *TrayApp
}
// NewTrayBuilder creates tray builder
func NewTrayBuilder(title, tooltip string) *TrayBuilder {
return &TrayBuilder{
app: NewTrayApp(title, tooltip),
}
}
func (tb *TrayBuilder) WithItem(title, tooltip string, onClick func()) *TrayBuilder {
tb.app.AddMenuItem(title, tooltip, onClick)
return tb
}
func (tb *TrayBuilder) WithSeparator() *TrayBuilder {
tb.app.AddSeparator()
return tb
}
func (tb *TrayBuilder) OnQuit(fn func()) *TrayBuilder {
tb.app.SetOnQuit(fn)
return tb
}
func (tb *TrayBuilder) Build() *TrayApp {
return tb.app
}
// 7. Advanced Tray Features
// TrayStatus holds tray status
type TrayStatus struct {
Enabled bool
Tooltip string
IconIndex int
}
// UpdateStatus updates tray status
func (ta *TrayApp) UpdateStatus(status TrayStatus) {
if status.Tooltip != "" {
ta.tray.SetTooltip(status.Tooltip)
}
fmt.Printf("[Tray] Status updated\n")
}
// SetIcon sets tray icon
func (ta *TrayApp) SetIcon(iconPath string) {
fmt.Printf("[Tray] Icon set to: %s\n", iconPath)
}
// ToggleVisibility toggles tray visibility
func (ta *TrayApp) ToggleVisibility() {
fmt.Println("[Tray] Visibility toggled")
}
// Usage Examples
func main() {
fmt.Println("=== Web Go System Tray Examples ===\n")
// 1. Basic tray icon
fmt.Println("--- 1. Basic Tray Icon ---")
tray := NewTrayIcon("My App", "My Application")
tray.AddMenuItem("Show", "Show window", func() {
fmt.Println("Show clicked")
})
tray.AddMenuItem("Hide", "Hide window", func() {
fmt.Println("Hide clicked")
})
tray.AddSeparator()
tray.AddMenuItem("Quit", "Quit application", func() {
fmt.Println("Quit clicked")
tray.Quit()
})
tray.OnQuit(func() {
fmt.Println("Cleanup on quit")
})
// Simulate running (in real app, this would be goroutine)
fmt.Println("Tray icon created (simulated)")
tray.running = true
time.Sleep(1 * time.Second)
tray.Quit()
// 2. Tray application
fmt.Println("
--- 2. Tray Application ---")
app := NewTrayApp("Tray App", "System Tray Application")
app.AddMenuItem("Open", "Open application", func() {
fmt.Println("Open clicked")
})
app.AddMenuItem("Settings", "Open settings", func() {
fmt.Println("Settings clicked")
})
app.AddSeparator()
app.SetOnQuit(func() {
fmt.Println("Application quitting")
})
fmt.Println("Tray application created (simulated)")
// 3. Tray builder
fmt.Println("
--- 3. Tray Builder ---")
builtApp := NewTrayBuilder("Builder App", "Built with Builder").
WithItem("Start", "Start service", func() {
fmt.Println("Service started")
}).
WithItem("Stop", "Stop service", func() {
fmt.Println("Service stopped")
}).
WithSeparator().
WithItem("Exit", "Exit application", func() {
fmt.Println("Exiting")
}).
OnQuit(func() {
fmt.Println("Builder cleanup")
}).
Build()
fmt.Println("Built app created (simulated)")
// 4. Status update
fmt.Println("
--- 4. Status Update ---")
builtApp.UpdateStatus(TrayStatus{
Enabled: true,
Tooltip: "Running",
})
// 5. Notification
fmt.Println("
--- 5. Notification ---")
builtApp.ShowNotification("Update Available", "Version 2.0 is ready")
// 6. Menu manager
fmt.Println("
--- 6. Menu Manager ---")
menu := NewTrayMenu()
menu.AddItem("File", "File operations", func() {
fmt.Println("File menu")
})
menu.AddItem("Edit", "Edit operations", func() {
fmt.Println("Edit menu")
})
menu.AddSeparator()
menu.AddItem("View", "View options", func() {
fmt.Println("View menu")
})
fmt.Printf("Menu created with %d items\n", len(menu.items))
fmt.Println("
=== All System Tray Examples Completed ===")
fmt.Println("Note: For full system tray functionality, install Systray or Fyne framework")
}