summaryrefslogtreecommitdiff
path: root/internal/tui/flamegraph/zoom_navigator.go
blob: e46085def7e357d74182519daa2accc66c539d35 (plain)
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
package flamegraph

import "strings"

// ZoomNavigator manages the zoom path, stack, and root node for the flamegraph
// view. It tracks the current zoom level, supports undo via a stack, and rebuilds
// the frame layout whenever the zoom target changes.
type ZoomNavigator struct {
	zoomPath      string
	zoomStack     []zoomState
	zoomRoot      *snapshotNode
	zoomLineWidth int
}

// currentRootPath returns the path of the current view root.
// When zoomed in, that is the zoom path; otherwise it is the first frame's path.
func (z *ZoomNavigator) currentRootPath(frames []tuiFrame) string {
	if z.zoomPath != "" {
		return z.zoomPath
	}
	if len(frames) == 0 {
		return ""
	}
	return frames[0].Path
}

// rootSnapshotPath returns the canonical root path derived from the snapshot or frames.
func (z *ZoomNavigator) rootSnapshotPath(snapshot *snapshotNode, frames []tuiFrame) string {
	if snapshot != nil {
		return frameName(snapshot.Name, 0)
	}
	if len(frames) > 0 {
		return frames[0].Path
	}
	return ""
}

// reset clears all zoom state and returns a status message.
func (z *ZoomNavigator) reset() string {
	z.zoomRoot = nil
	z.zoomPath = ""
	z.zoomStack = nil
	z.zoomLineWidth = 0
	return "Zoom reset to root"
}

// alreadyAtRoot reports whether no zoom is active and the stack is empty.
func (z *ZoomNavigator) alreadyAtRoot() bool {
	return z.zoomRoot == nil && len(z.zoomStack) == 0
}

// buildZoomStack builds the ancestor zoom stack for a direct deep-zoom path.
// It creates entries for every path prefix so undo walks back up one step at a
// time: root → A → A/A1 etc.
func buildZoomStack(path string) []zoomState {
	parts := strings.Split(path, pathSeparator)
	if len(parts) <= 1 {
		return nil
	}
	stack := []zoomState{{path: ""}}
	for idx := 1; idx < len(parts)-1; idx++ {
		stack = append(stack, zoomState{path: strings.Join(parts[:idx+1], pathSeparator)})
	}
	return stack
}