turbo-editors/turbo-corepublic Fork 0
d662cebdb65b319885da903daf7eff9ab1bfbb78
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

🛟 Updated. 28d5985 · on d662cebdb65b319885da903daf7eff9ab1bfbb78 · k33g · 19h ago
view_events.go · 141 lines · 3.2 KBGo Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package filetree

import "github.com/gdamore/tcell/v2"

// HandleKey walks the tree, opens branches and chooses files.
//
// Left and right do what they do in every tree: right opens a closed branch
// and steps into an open one, left closes an open branch and steps out of a
// closed one, so the two together walk the shape without ever being a no-op.
func (v *View) HandleKey(ev *tcell.EventKey) bool {
	if !v.Focused() {
		return false
	}
	if v.handleMovementKey(ev) {
		return true
	}

	switch ev.Key() {
	case tcell.KeyRight:
		v.expandOrDescend()
	case tcell.KeyLeft:
		v.collapseOrAscend()
	case tcell.KeyEnter:
		v.Choose()
	case tcell.KeyF5, tcell.KeyCtrlR:
		v.Refresh()
	default:
		return false
	}
	return true
}

// handleMovementKey deals with the keys that only move the highlight.
func (v *View) handleMovementKey(ev *tcell.EventKey) bool {
	page := max(v.Bounds().H, 1)

	switch ev.Key() {
	case tcell.KeyUp:
		v.move(-1)
	case tcell.KeyDown:
		v.move(1)
	case tcell.KeyPgUp:
		v.move(-page)
	case tcell.KeyPgDn:
		v.move(page)
	case tcell.KeyHome:
		v.moveTo(0)
	case tcell.KeyEnd:
		v.moveTo(len(v.tree.Rows()) - 1)
	default:
		return false
	}
	return true
}

// move shifts the highlight by a number of rows, stopping at either end.
func (v *View) move(by int) { v.moveTo(v.selected + by) }

// moveTo puts the highlight on a row, clamped to the rows there are.
func (v *View) moveTo(index int) {
	v.selected = min(max(index, 0), max(len(v.tree.Rows())-1, 0))
}

// expandOrDescend opens a closed directory, or steps into one already open.
func (v *View) expandOrDescend() {
	node := v.Selected()
	if node == nil {
		return
	}
	if node.IsDir() && !node.Expanded() {
		node.Expand()
		return
	}
	v.move(1)
}

// collapseOrAscend closes an open directory, or steps out to the parent of
// anything else.
func (v *View) collapseOrAscend() {
	node := v.Selected()
	if node == nil {
		return
	}
	if node.IsDir() && node.Expanded() {
		node.Collapse()
		v.keepSelectionInRange()
		return
	}
	v.selectParent()
}

// selectParent moves the highlight to the branch the current row sits in.
//
// The parent is the nearest row above with a smaller depth, which is what the
// eye reads as "the folder this is in" — and needs no parent pointer on the
// nodes to find.
func (v *View) selectParent() {
	rows := v.tree.Rows()
	if v.selected <= 0 || v.selected >= len(rows) {
		return
	}

	depth := rows[v.selected].Depth
	for i := v.selected - 1; i >= 0; i-- {
		if rows[i].Depth < depth {
			v.selected = i
			return
		}
	}
}

// HandleMouse highlights the clicked row, chooses it on a second click, and
// scrolls with the wheel.
func (v *View) HandleMouse(ev *tcell.EventMouse) bool {
	if !v.Bounds().Contains(ev.Position()) {
		return false
	}

	switch ev.Buttons() {
	case tcell.WheelUp:
		v.move(-wheelStep)
	case tcell.WheelDown:
		v.move(wheelStep)
	case tcell.Button1:
		v.clickRow(ev)
	}
	return true
}

// clickRow selects the row under the pointer, or acts on it when it was
// already the selected one — the same second-click rule the list boxes use.
func (v *View) clickRow(ev *tcell.EventMouse) {
	_, y := ev.Position()
	index := v.top + y - v.Bounds().Y

	if index == v.selected {
		v.Choose()
		return
	}
	v.moveTo(index)
}