| 🛟 Updated. 28d5985 k33g 18h ago | 1 | // The project tree window: the files of the project the editor was started |
| 2 | // in, shown as a tree you can open a file from. |
| 3 | |
| 4 | package app |
| 5 | |
| 6 | import ( |
| 7 | "os" |
| 8 | |
| 9 | "codeberg.org/turbo-editors/turbo-core/filetree" |
| 10 | "codeberg.org/turbo-editors/turbo-core/ui" |
| 11 | ) |
| 12 | |
| 13 | // ProjectTree opens a window showing the project's files, or brings the one |
| 14 | // already open to the front. |
| 15 | // |
| 16 | // There is at most one, because a second tree on the same project would be two |
| 17 | // views of one thing with nothing to tell them apart — and the project cannot |
| 18 | // change while the editor runs. |
| 19 | // |
| 20 | // The tree is rooted at the directory the editor was started in, the same rule |
| 21 | // .turbo-go/settings.toml follows, so "the project" means one thing everywhere |
| 22 | // in the editor. |
| 23 | func (a *App) ProjectTree() { |
| 24 | if a.treeWindow != nil { |
| 25 | a.desktop.Focus(a.treeWindow) |
| 26 | return |
| 27 | } |
| 28 | |
| 29 | root, err := os.Getwd() |
| 30 | if err != nil { |
| 31 | a.ShowMessage("Project tree", "Cannot tell which directory this is:\n"+err.Error()) |
| 32 | return |
| 33 | } |
| 34 | |
| 35 | view, err := filetree.NewView(root) |
| 36 | if err != nil { |
| 37 | a.ShowMessage("Project tree", err.Error()) |
| 38 | return |
| 39 | } |
| 40 | view.OnOpen = a.Open |
| 41 | |
| 42 | window := ui.NewWindow(view.Title(), view) |
| 43 | window.SetBounds(a.newWindowBounds()) |
| 44 | window.OnClose = func() bool { a.closeTree(); return true } |
| 45 | |
| 46 | a.desktop.Add(window) |
| 47 | a.windowsOpened++ |
| 48 | a.treeWindow, a.treeView = window, view |
| 49 | } |
| 50 | |
| 51 | // closeTree takes the tree window away and forgets it, so the next F9 opens a |
| 52 | // fresh one rather than trying to focus a window that has gone. |
| 53 | func (a *App) closeTree() { |
| 54 | if a.treeWindow == nil { |
| 55 | return |
| 56 | } |
| 57 | a.desktop.Remove(a.treeWindow) |
| 58 | a.treeWindow, a.treeView = nil, nil |
| 59 | a.completion.Hide() |
| 60 | } |
| 61 | |
| 62 | // isTreeWindow reports whether a window holds the project tree. The file |
| 63 | // actions use it to leave the tree alone. |
| 64 | func (a *App) isTreeWindow(window *ui.Window) bool { |
| 65 | return window != nil && window == a.treeWindow |
| 66 | } |
| 67 | |
| 68 | // refreshTree re-reads the project, so a file just written turns up without |
| 69 | // anyone asking for it. |
| 70 | // |
| 71 | // It runs after a save rather than on a timer or a filesystem watch: saving is |
| 72 | // the one moment the editor knows the project has changed, and watching the |
| 73 | // disk would mean a third dependency. |
| 74 | func (a *App) refreshTree() { |
| 75 | if a.treeView != nil { |
| 76 | a.treeView.Refresh() |
| 77 | } |
| 78 | } |