v / cmd / v2 / guiprof / events.v
233 lines · 207 sloc · 4.93 KB · a76973f101edbe08f2df8b6ee19784ede8bfe966
Raw
1// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module main
5
6import gg
7import os
8import v2.profiler
9
10// handle_event processes user input events
11pub fn handle_event(e &gg.Event, mut app App) {
12 match e.typ {
13 .mouse_down {
14 handle_mouse_click(e, mut app)
15 }
16 .mouse_move {
17 handle_mouse_move(e, mut app)
18 }
19 .key_down {
20 handle_key_down(e, mut app)
21 }
22 else {}
23 }
24}
25
26// handle_mouse_click processes mouse click events
27fn handle_mouse_click(e &gg.Event, mut app App) {
28 x := e.mouse_x
29 y := e.mouse_y
30
31 // Check which region was clicked
32 hist_y := f32(app.header_height)
33 hist_h := f32(app.histogram_height)
34 timeline_y := hist_y + hist_h
35 timeline_h := f32(app.timeline_height)
36 ctrl_y := timeline_y + timeline_h
37 ctrl_h := f32(app.controls_height)
38
39 // Click in histogram area
40 if y >= hist_y && y < hist_y + hist_h {
41 handle_histogram_click(x, y, mut app)
42 return
43 }
44
45 // Click in timeline area
46 if y >= timeline_y && y < timeline_y + timeline_h {
47 handle_timeline_click(x, y, mut app)
48 return
49 }
50
51 // Click in controls area
52 if y >= ctrl_y && y < ctrl_y + ctrl_h {
53 handle_controls_click(x, y, mut app)
54 return
55 }
56}
57
58// handle_histogram_click selects a frame from the histogram
59fn handle_histogram_click(x f32, y f32, mut app App) {
60 frames := app.cached_frames
61 if frames.len == 0 {
62 return
63 }
64
65 w := f32(app.gg.width)
66 margin := f32(40)
67 bar_area_width := w - margin * 2
68
69 // Calculate frame index
70 relative_x := x - margin
71 if relative_x < 0 || relative_x > bar_area_width {
72 return
73 }
74
75 bar_width := bar_area_width / f32(frames.len)
76 frame_idx := int(relative_x / bar_width)
77
78 if frame_idx >= 0 && frame_idx < frames.len {
79 app.selected_frame = frame_idx
80 // Select first allocation in this frame
81 allocs := app.cached_allocs
82 for i, alloc in allocs {
83 if alloc.frame == u64(frame_idx) {
84 app.selected_alloc = i
85 break
86 }
87 }
88 }
89}
90
91// handle_timeline_click scrubs the timeline
92fn handle_timeline_click(x f32, y f32, mut app App) {
93 // Same logic as histogram click for frame selection
94 handle_histogram_click(x, y, mut app)
95}
96
97// handle_controls_click handles filter button clicks
98fn handle_controls_click(x f32, y f32, mut app App) {
99 // Filter buttons start at x=80
100 btn_start := f32(80)
101 btn_w := f32(60)
102 btn_gap := f32(10)
103
104 relative_x := x - btn_start
105 if relative_x < 0 {
106 return
107 }
108
109 btn_idx := int(relative_x / (btn_w + btn_gap))
110 modes := [FilterMode.all, FilterMode.new_not_freed, FilterMode.large, FilterMode.current_frame]
111
112 if btn_idx >= 0 && btn_idx < modes.len {
113 app.filter_mode = modes[btn_idx]
114 }
115}
116
117// handle_mouse_move updates hover state
118fn handle_mouse_move(e &gg.Event, mut app App) {
119 x := e.mouse_x
120 y := e.mouse_y
121
122 hist_y := f32(app.header_height)
123 hist_h := f32(app.histogram_height)
124
125 // Check if hovering over histogram
126 if y >= hist_y && y < hist_y + hist_h {
127 frames := app.cached_frames
128 if frames.len > 0 {
129 w := f32(app.gg.width)
130 margin := f32(40)
131 bar_area_width := w - margin * 2
132 relative_x := x - margin
133
134 if relative_x >= 0 && relative_x <= bar_area_width {
135 bar_width := bar_area_width / f32(frames.len)
136 app.hover_frame = int(relative_x / bar_width)
137 if app.hover_frame >= frames.len {
138 app.hover_frame = -1
139 }
140 } else {
141 app.hover_frame = -1
142 }
143 }
144 } else {
145 app.hover_frame = -1
146 }
147}
148
149// handle_key_down processes keyboard input
150fn handle_key_down(e &gg.Event, mut app App) {
151 match e.key_code {
152 .left {
153 // Previous frame
154 if app.selected_frame > 0 {
155 app.selected_frame--
156 }
157 }
158 .right {
159 // Next frame
160 frames := app.cached_frames
161 if app.selected_frame < frames.len - 1 {
162 app.selected_frame++
163 }
164 }
165 .up {
166 // Previous allocation
167 if app.selected_alloc > 0 {
168 app.selected_alloc--
169 }
170 }
171 .down {
172 // Next allocation
173 allocs := app.cached_allocs
174 if app.selected_alloc < allocs.len - 1 {
175 app.selected_alloc++
176 }
177 }
178 .enter {
179 // Open source file in editor
180 open_in_editor(app)
181 }
182 .f {
183 // Cycle filter modes
184 app.filter_mode = match app.filter_mode {
185 .all { .new_not_freed }
186 .new_not_freed { .large }
187 .large { .current_frame }
188 .current_frame { .all }
189 }
190 }
191 .r {
192 // Reset profiler data
193 if !app.demo_mode {
194 profiler.reset()
195 }
196 }
197 .escape {
198 // Clear selection
199 app.selected_frame = -1
200 app.selected_alloc = -1
201 }
202 .space {
203 // Toggle demo mode
204 app.demo_mode = !app.demo_mode
205 if app.demo_mode {
206 // Initialize demo data
207 init_demo_data(mut app)
208 }
209 }
210 else {}
211 }
212}
213
214// open_in_editor opens the selected allocation's source file in VS Code
215fn open_in_editor(app &App) {
216 if app.selected_alloc < 0 {
217 return
218 }
219
220 allocs := app.cached_allocs
221 if app.selected_alloc >= allocs.len {
222 return
223 }
224
225 alloc := allocs[app.selected_alloc]
226 if alloc.file.len == 0 {
227 return
228 }
229
230 // Try to open in VS Code with line number
231 cmd := 'code -g "${alloc.file}:${alloc.line}"'
232 os.execute(cmd)
233}
234