Skip to content

Commit d864edb

Browse files
authored
Add support for clicking on arrows in the file list to expand/collapse directories (#5365)
### PR Description This PR adds support for clicking on arrows in the file changes list view, so that a mouse can be used to expand/collapse directories. This enhancement was raised here as issue #5088.
2 parents dcfdf40 + ee3bb06 commit d864edb

20 files changed

+358
-24
lines changed

pkg/gui/context/base_context.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ type BaseContext struct {
1515

1616
keybindingsFns []types.KeybindingsFn
1717
mouseKeybindingsFns []types.MouseKeybindingsFn
18-
onClickFn func() error
18+
onDoubleClickFn func() error
19+
onClickFn func(opts gocui.ViewMouseBindingOpts) error
1920
onClickFocusedMainViewFn onClickFocusedMainViewFn
2021
onRenderToMainFn func()
2122
onFocusFns []onFocusFn
@@ -140,12 +141,22 @@ func (self *BaseContext) ClearAllAttachedControllerFunctions() {
140141
self.mouseKeybindingsFns = nil
141142
self.onFocusFns = nil
142143
self.onFocusLostFns = nil
144+
self.onDoubleClickFn = nil
143145
self.onClickFn = nil
144146
self.onClickFocusedMainViewFn = nil
145147
self.onRenderToMainFn = nil
146148
}
147149

148-
func (self *BaseContext) AddOnClickFn(fn func() error) {
150+
func (self *BaseContext) AddOnDoubleClickFn(fn func() error) {
151+
if fn != nil {
152+
if self.onDoubleClickFn != nil {
153+
panic("only one controller is allowed to set an onDoubleClickFn")
154+
}
155+
self.onDoubleClickFn = fn
156+
}
157+
}
158+
159+
func (self *BaseContext) AddOnClickFn(fn func(opts gocui.ViewMouseBindingOpts) error) {
149160
if fn != nil {
150161
if self.onClickFn != nil {
151162
panic("only one controller is allowed to set an onClickFn")
@@ -163,7 +174,11 @@ func (self *BaseContext) AddOnClickFocusedMainViewFn(fn onClickFocusedMainViewFn
163174
}
164175
}
165176

166-
func (self *BaseContext) GetOnClick() func() error {
177+
func (self *BaseContext) GetOnDoubleClick() func() error {
178+
return self.onDoubleClickFn
179+
}
180+
181+
func (self *BaseContext) GetOnClick() func(opts gocui.ViewMouseBindingOpts) error {
167182
return self.onClickFn
168183
}
169184

pkg/gui/context/suggestions_context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@ func (self *SuggestionsContext) RangeSelectEnabled() bool {
8989
return false
9090
}
9191

92-
func (self *SuggestionsContext) GetOnClick() func() error {
92+
func (self *SuggestionsContext) GetOnDoubleClick() func() error {
9393
return self.State.OnConfirm
9494
}

pkg/gui/controllers/attach.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ func AttachControllers(context types.Context, controllers ...types.IController)
66
for _, controller := range controllers {
77
context.AddKeybindingsFn(controller.GetKeybindings)
88
context.AddMouseKeybindingsFn(controller.GetMouseKeybindings)
9+
context.AddOnDoubleClickFn(controller.GetOnDoubleClick())
910
context.AddOnClickFn(controller.GetOnClick())
1011
context.AddOnClickFocusedMainViewFn(controller.GetOnClickFocusedMainView())
1112
context.AddOnRenderToMainFn(controller.GetOnRenderToMain())

pkg/gui/controllers/base_controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ func (self *baseController) GetMouseKeybindings(opts types.KeybindingsOpts) []*g
1515
return nil
1616
}
1717

18-
func (self *baseController) GetOnClick() func() error {
18+
func (self *baseController) GetOnDoubleClick() func() error {
1919
return nil
2020
}
2121

2222
func (self *baseController) GetOnClickFocusedMainView() func(mainViewName string, clickedLineIdx int) error {
2323
return nil
2424
}
2525

26+
func (self *baseController) GetOnClick() func(opts gocui.ViewMouseBindingOpts) error {
27+
return nil
28+
}
29+
2630
func (self *baseController) GetOnRenderToMain() func() {
2731
return nil
2832
}

pkg/gui/controllers/commits_files_controller.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,30 @@ func (self *CommitFilesController) context() *context.CommitFilesContext {
142142
return self.c.Contexts().CommitFiles
143143
}
144144

145+
func (self *CommitFilesController) GetOnClick() func(opts gocui.ViewMouseBindingOpts) error {
146+
return func(opts gocui.ViewMouseBindingOpts) error {
147+
clickedIdx := self.context().GetSelectedLineIdx()
148+
node := self.context().CommitFileTreeViewModel.Get(clickedIdx)
149+
if node == nil || node.File != nil {
150+
return nil
151+
}
152+
153+
// The arrow is at column visualDepth*2 (after indentation of 2 spaces per level).
154+
// Only treat clicks on the arrow and the trailing space as arrow clicks.
155+
visualDepth := self.context().CommitFileTreeViewModel.GetVisualDepth(clickedIdx)
156+
arrowStartCol := visualDepth * 2
157+
arrowEndCol := arrowStartCol + 1
158+
if opts.X < arrowStartCol || opts.X > arrowEndCol {
159+
return nil
160+
}
161+
162+
self.context().CommitFileTreeViewModel.ToggleCollapsed(node.GetInternalPath())
163+
self.c.PostRefreshUpdate(self.context())
164+
165+
return nil
166+
}
167+
}
168+
145169
func (self *CommitFilesController) GetOnRenderToMain() func() {
146170
return func() {
147171
node := self.context().GetSelected()

pkg/gui/controllers/files_controller.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,30 @@ func (self *FilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*
229229
}
230230
}
231231

232+
func (self *FilesController) GetOnClick() func(opts gocui.ViewMouseBindingOpts) error {
233+
return func(opts gocui.ViewMouseBindingOpts) error {
234+
clickedIdx := self.context().GetSelectedLineIdx()
235+
node := self.context().FileTreeViewModel.Get(clickedIdx)
236+
if node == nil || node.File != nil {
237+
return nil
238+
}
239+
240+
// The arrow is at column visualDepth*2 (after indentation of 2 spaces per level).
241+
// Only treat clicks on the arrow and the trailing space as arrow clicks.
242+
visualDepth := self.context().FileTreeViewModel.GetVisualDepth(clickedIdx)
243+
arrowStartCol := visualDepth * 2
244+
arrowEndCol := arrowStartCol + 1
245+
if opts.X < arrowStartCol || opts.X > arrowEndCol {
246+
return nil
247+
}
248+
249+
self.context().FileTreeViewModel.ToggleCollapsed(node.GetInternalPath())
250+
self.c.PostRefreshUpdate(self.context())
251+
252+
return nil
253+
}
254+
}
255+
232256
func (self *FilesController) GetOnRenderToMain() func() {
233257
return func() {
234258
self.c.Helpers().Diff.WithDiffModeCheck(func() {
@@ -329,7 +353,7 @@ func (self *FilesController) GetOnRenderToMain() func() {
329353
}
330354
}
331355

332-
func (self *FilesController) GetOnClick() func() error {
356+
func (self *FilesController) GetOnDoubleClick() func() error {
333357
return self.withItemGraceful(func(node *filetree.FileNode) error {
334358
return self.press([]*filetree.FileNode{node})
335359
})

pkg/gui/controllers/list_controller.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,17 @@ func (self *ListController) HandleClick(opts gocui.ViewMouseBindingOpts) error {
243243

244244
self.context.GetList().SetSelection(newSelectedLineIdx)
245245

246-
if opts.IsDoubleClick && alreadyFocused && self.context.GetOnClick() != nil {
247-
return self.context.GetOnClick()()
246+
if opts.IsDoubleClick && alreadyFocused && self.context.GetOnDoubleClick() != nil {
247+
return self.context.GetOnDoubleClick()()
248248
}
249+
249250
self.context.HandleFocus(types.OnFocusOpts{})
251+
252+
// Let view-specific controllers do additional click handling
253+
if self.context.GetOnClick() != nil {
254+
return self.context.GetOnClick()(opts)
255+
}
256+
250257
return nil
251258
}
252259

pkg/gui/controllers/menu_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.
5555
return bindings
5656
}
5757

58-
func (self *MenuController) GetOnClick() func() error {
58+
func (self *MenuController) GetOnDoubleClick() func() error {
5959
return self.withItemGraceful(self.press)
6060
}
6161

pkg/gui/controllers/remotes_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (self *RemotesController) GetOnRenderToMain() func() {
120120
}
121121
}
122122

123-
func (self *RemotesController) GetOnClick() func() error {
123+
func (self *RemotesController) GetOnDoubleClick() func() error {
124124
return self.withItemGraceful(self.enter)
125125
}
126126

pkg/gui/controllers/submodules_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
102102
}
103103
}
104104

105-
func (self *SubmodulesController) GetOnClick() func() error {
105+
func (self *SubmodulesController) GetOnDoubleClick() func() error {
106106
return self.withItemGraceful(self.enter)
107107
}
108108

0 commit comments

Comments
 (0)