|
3 | 3 | package guimain
|
4 | 4 |
|
5 | 5 | import (
|
6 |
| - "image/color" |
7 | 6 | "os"
|
| 7 | + "runtime" |
8 | 8 |
|
9 | 9 | "fyne.io/fyne/v2"
|
10 | 10 | "fyne.io/fyne/v2/app"
|
11 |
| - "fyne.io/fyne/v2/canvas" |
| 11 | + "fyne.io/fyne/v2/container" |
12 | 12 | "fyne.io/fyne/v2/dialog"
|
13 | 13 | "fyne.io/fyne/v2/layout"
|
| 14 | + "fyne.io/fyne/v2/theme" |
14 | 15 | "fyne.io/fyne/v2/widget"
|
15 |
| - "golang.org/x/image/colornames" |
16 | 16 |
|
17 | 17 | "lazyhacker.dev/getgo/internal/lib"
|
18 | 18 | )
|
19 | 19 |
|
20 |
| -func LoadGUI(filename, checksum string) { |
| 20 | +/* GetGo describes the elements of the main UI and the data needed by the UI.*/ |
| 21 | +type GetGo struct { |
| 22 | + parent fyne.Window // reference the parent window for the app. |
| 23 | + operatingSystem string // GOOS version |
| 24 | + architecture string // GOARCH (e.g. amd64, arm, etc.) |
| 25 | + kind string // archive or installer |
| 26 | + savepath string // directory to save to |
| 27 | + filename string // Go binary to download |
| 28 | + shasum string // SHA256 of the binary |
| 29 | + |
| 30 | + formInput *widget.Form // Input form for OS, Arch and Kind |
| 31 | + |
| 32 | + // The read-only file info. Using widget.Form as a cheat for the layout. |
| 33 | + formFileInfo *widget.Form |
| 34 | + |
| 35 | + lblChecksumValue *widget.Label // Label to display the SHA256 value. |
| 36 | + lblSavePath *widget.Label // Label to show the directory to save to. |
| 37 | + lblFileName *widget.Label // Label to show the binary filename to download |
| 38 | + |
| 39 | + iconDir *widget.Icon |
| 40 | + |
| 41 | + btnDownload *widget.Button // button to start the download |
| 42 | + btnSaveFile *widget.Button // button to pick the save directory |
| 43 | + |
| 44 | + saveDirWidget fyne.CanvasObject // container for the save button and label. |
| 45 | +} |
| 46 | + |
| 47 | +/* downloadGo starts the downloading and the corresponding dialogs. */ |
| 48 | +func (a *GetGo) downloadGo() { |
| 49 | + a.filename, a.shasum, _ = lib.LatestVersion(a.operatingSystem, a.architecture, a.kind) |
| 50 | + a.lblFileName.SetText(a.filename) |
| 51 | + a.lblChecksumValue.SetText(a.shasum) |
| 52 | + prog := dialog.NewProgressInfinite("Downloading", "", a.parent) |
| 53 | + prog.Show() |
| 54 | + err := lib.DownloadAndVerify(a.savepath, a.filename, a.shasum, "") |
| 55 | + prog.Hide() |
| 56 | + if err != nil { |
| 57 | + dialog.ShowError(err, a.parent) |
| 58 | + return |
| 59 | + } |
| 60 | + dialog.ShowInformation("Complete!", "File downloaded.", a.parent) |
| 61 | + |
| 62 | +} |
| 63 | + |
| 64 | +/* |
| 65 | +Init should be called first to initialize the UI elements and default values. |
| 66 | +It can be called again to reset the UI elements back to the defaults. |
| 67 | +*/ |
| 68 | +func (a *GetGo) Init(w fyne.Window) { |
| 69 | + |
| 70 | + defaultkind := "archive" |
| 71 | + |
| 72 | + pwd, _ := os.Getwd() |
| 73 | + |
| 74 | + if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { |
| 75 | + defaultkind = "installer" |
| 76 | + } |
| 77 | + |
| 78 | + a.parent = w |
| 79 | + a.operatingSystem = runtime.GOOS |
| 80 | + a.architecture = runtime.GOARCH |
| 81 | + a.savepath = pwd |
| 82 | + a.kind = defaultkind |
| 83 | + a.lblChecksumValue = widget.NewLabel("") |
| 84 | + a.lblFileName = widget.NewLabel("") |
| 85 | + |
| 86 | + // Select boxes for OS, arch and kind |
| 87 | + selOS := widget.NewSelect(lib.OperatingSystems, |
| 88 | + func(s string) { |
| 89 | + a.operatingSystem = s |
| 90 | + }, |
| 91 | + ) |
| 92 | + selArch := widget.NewSelect(lib.Architectures, func(s string) { |
| 93 | + a.architecture = s |
| 94 | + }, |
| 95 | + ) |
| 96 | + selKind := widget.NewSelect( |
| 97 | + []string{"archive", "installer"}, |
| 98 | + func(s string) { |
| 99 | + a.kind = s |
| 100 | + }, |
| 101 | + ) |
| 102 | + |
| 103 | + // Add the selection dropdowns into a single form. |
| 104 | + a.formInput = widget.NewForm( |
| 105 | + widget.NewFormItem("OS", selOS), |
| 106 | + widget.NewFormItem("Arch", selArch), |
| 107 | + widget.NewFormItem("Kind", selKind), |
| 108 | + ) |
| 109 | + |
| 110 | + // Set the default selection. |
| 111 | + selOS.SetSelected(a.operatingSystem) |
| 112 | + selArch.SetSelected(a.architecture) |
| 113 | + selKind.SetSelected(a.kind) |
| 114 | + |
| 115 | + a.btnSaveFile = widget.NewButtonWithIcon("", theme.FolderIcon(), |
| 116 | + func() { |
| 117 | + dialog.ShowFolderOpen( |
| 118 | + func(uri fyne.ListableURI, err error) { |
| 119 | + // TODO: Should look into data binding for these fields. |
| 120 | + a.savepath = uri.Path() |
| 121 | + a.lblSavePath.SetText(uri.Path()) |
| 122 | + }, a.parent) |
| 123 | + |
| 124 | + }, |
| 125 | + ) |
| 126 | + |
| 127 | + // Default to the directory the app was launched. |
| 128 | + a.lblSavePath = widget.NewLabel(pwd) |
| 129 | + |
| 130 | + a.formFileInfo = widget.NewForm( |
| 131 | + widget.NewFormItem("File", a.lblFileName), |
| 132 | + widget.NewFormItem("Sha256", a.lblChecksumValue), |
| 133 | + ) |
| 134 | + |
| 135 | + a.btnDownload = widget.NewButton("Download", |
| 136 | + func() { |
| 137 | + a.downloadGo() |
| 138 | + }) |
| 139 | + |
| 140 | + // Want two column side-by-side layout similar to a form but widget.Form |
| 141 | + // takes a string and not an icon for the input label. |
| 142 | + a.saveDirWidget = container.New(layout.NewHBoxLayout(), |
| 143 | + a.btnSaveFile, |
| 144 | + a.lblSavePath, |
| 145 | + ) |
| 146 | +} |
| 147 | + |
| 148 | +/* |
| 149 | +LoadGUI is the main entry point to start an Fyne app. It will initialize an |
| 150 | +app, create a window, set the container and start the app. |
| 151 | +*/ |
| 152 | +func LoadGUI() { |
21 | 153 | a := app.New()
|
22 | 154 | w := a.NewWindow("GetGo")
|
23 | 155 |
|
24 |
| - wd, _ := os.Getwd() |
25 |
| - dirLabel := canvas.NewText("Directory", colornames.Gray) |
26 |
| - dirValue := canvas.NewText(wd, color.White) |
27 |
| - fileLabel := canvas.NewText("Latest Stable", colornames.Gray) |
28 |
| - fileValue := canvas.NewText(filename, color.White) |
29 |
| - shaLabel := canvas.NewText("Sha256", colornames.Gray) |
30 |
| - shaValue := canvas.NewText(checksum, color.White) |
31 |
| - |
32 |
| - formGrid := fyne.NewContainerWithLayout( |
33 |
| - layout.NewFormLayout(), |
34 |
| - dirLabel, dirValue, |
35 |
| - fileLabel, fileValue, |
36 |
| - shaLabel, shaValue) |
37 |
| - |
38 |
| - grid := fyne.NewContainerWithLayout( |
39 |
| - layout.NewVBoxLayout(), |
40 |
| - formGrid, |
41 |
| - widget.NewButton("Download Latest", |
42 |
| - func() { |
43 |
| - prog := dialog.NewProgressInfinite("Downloading", fileValue.Text, w) |
44 |
| - prog.Show() |
45 |
| - err := lib.DownloadAndVerify(dirValue.Text, filename, checksum, "") |
46 |
| - prog.Hide() |
47 |
| - if err != nil { |
48 |
| - dialog.ShowError(err, w) |
49 |
| - return |
50 |
| - } |
51 |
| - dialog.ShowInformation("Complete!", "File downloaded.", w) |
52 |
| - }, |
53 |
| - ), |
54 |
| - ) |
55 |
| - w.SetContent(grid) |
| 156 | + ui := GetGo{} |
| 157 | + ui.Init(w) |
| 158 | + c := container.New(layout.NewVBoxLayout(), |
| 159 | + ui.formInput, |
| 160 | + ui.saveDirWidget, |
| 161 | + ui.btnDownload, |
| 162 | + ui.formFileInfo, |
| 163 | + ) |
| 164 | + |
| 165 | + w.SetContent(c) |
56 | 166 | w.ShowAndRun()
|
57 | 167 | }
|
0 commit comments