234 lines
4.9 KiB
V
234 lines
4.9 KiB
V
// Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
module main
|
|
|
|
import gg
|
|
import os
|
|
import v2.profiler
|
|
|
|
// handle_event processes user input events
|
|
pub fn handle_event(e &gg.Event, mut app App) {
|
|
match e.typ {
|
|
.mouse_down {
|
|
handle_mouse_click(e, mut app)
|
|
}
|
|
.mouse_move {
|
|
handle_mouse_move(e, mut app)
|
|
}
|
|
.key_down {
|
|
handle_key_down(e, mut app)
|
|
}
|
|
else {}
|
|
}
|
|
}
|
|
|
|
// handle_mouse_click processes mouse click events
|
|
fn handle_mouse_click(e &gg.Event, mut app App) {
|
|
x := e.mouse_x
|
|
y := e.mouse_y
|
|
|
|
// Check which region was clicked
|
|
hist_y := f32(app.header_height)
|
|
hist_h := f32(app.histogram_height)
|
|
timeline_y := hist_y + hist_h
|
|
timeline_h := f32(app.timeline_height)
|
|
ctrl_y := timeline_y + timeline_h
|
|
ctrl_h := f32(app.controls_height)
|
|
|
|
// Click in histogram area
|
|
if y >= hist_y && y < hist_y + hist_h {
|
|
handle_histogram_click(x, y, mut app)
|
|
return
|
|
}
|
|
|
|
// Click in timeline area
|
|
if y >= timeline_y && y < timeline_y + timeline_h {
|
|
handle_timeline_click(x, y, mut app)
|
|
return
|
|
}
|
|
|
|
// Click in controls area
|
|
if y >= ctrl_y && y < ctrl_y + ctrl_h {
|
|
handle_controls_click(x, y, mut app)
|
|
return
|
|
}
|
|
}
|
|
|
|
// handle_histogram_click selects a frame from the histogram
|
|
fn handle_histogram_click(x f32, y f32, mut app App) {
|
|
frames := app.cached_frames
|
|
if frames.len == 0 {
|
|
return
|
|
}
|
|
|
|
w := f32(app.gg.width)
|
|
margin := f32(40)
|
|
bar_area_width := w - margin * 2
|
|
|
|
// Calculate frame index
|
|
relative_x := x - margin
|
|
if relative_x < 0 || relative_x > bar_area_width {
|
|
return
|
|
}
|
|
|
|
bar_width := bar_area_width / f32(frames.len)
|
|
frame_idx := int(relative_x / bar_width)
|
|
|
|
if frame_idx >= 0 && frame_idx < frames.len {
|
|
app.selected_frame = frame_idx
|
|
// Select first allocation in this frame
|
|
allocs := app.cached_allocs
|
|
for i, alloc in allocs {
|
|
if alloc.frame == u64(frame_idx) {
|
|
app.selected_alloc = i
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle_timeline_click scrubs the timeline
|
|
fn handle_timeline_click(x f32, y f32, mut app App) {
|
|
// Same logic as histogram click for frame selection
|
|
handle_histogram_click(x, y, mut app)
|
|
}
|
|
|
|
// handle_controls_click handles filter button clicks
|
|
fn handle_controls_click(x f32, y f32, mut app App) {
|
|
// Filter buttons start at x=80
|
|
btn_start := f32(80)
|
|
btn_w := f32(60)
|
|
btn_gap := f32(10)
|
|
|
|
relative_x := x - btn_start
|
|
if relative_x < 0 {
|
|
return
|
|
}
|
|
|
|
btn_idx := int(relative_x / (btn_w + btn_gap))
|
|
modes := [FilterMode.all, FilterMode.new_not_freed, FilterMode.large, FilterMode.current_frame]
|
|
|
|
if btn_idx >= 0 && btn_idx < modes.len {
|
|
app.filter_mode = modes[btn_idx]
|
|
}
|
|
}
|
|
|
|
// handle_mouse_move updates hover state
|
|
fn handle_mouse_move(e &gg.Event, mut app App) {
|
|
x := e.mouse_x
|
|
y := e.mouse_y
|
|
|
|
hist_y := f32(app.header_height)
|
|
hist_h := f32(app.histogram_height)
|
|
|
|
// Check if hovering over histogram
|
|
if y >= hist_y && y < hist_y + hist_h {
|
|
frames := app.cached_frames
|
|
if frames.len > 0 {
|
|
w := f32(app.gg.width)
|
|
margin := f32(40)
|
|
bar_area_width := w - margin * 2
|
|
relative_x := x - margin
|
|
|
|
if relative_x >= 0 && relative_x <= bar_area_width {
|
|
bar_width := bar_area_width / f32(frames.len)
|
|
app.hover_frame = int(relative_x / bar_width)
|
|
if app.hover_frame >= frames.len {
|
|
app.hover_frame = -1
|
|
}
|
|
} else {
|
|
app.hover_frame = -1
|
|
}
|
|
}
|
|
} else {
|
|
app.hover_frame = -1
|
|
}
|
|
}
|
|
|
|
// handle_key_down processes keyboard input
|
|
fn handle_key_down(e &gg.Event, mut app App) {
|
|
match e.key_code {
|
|
.left {
|
|
// Previous frame
|
|
if app.selected_frame > 0 {
|
|
app.selected_frame--
|
|
}
|
|
}
|
|
.right {
|
|
// Next frame
|
|
frames := app.cached_frames
|
|
if app.selected_frame < frames.len - 1 {
|
|
app.selected_frame++
|
|
}
|
|
}
|
|
.up {
|
|
// Previous allocation
|
|
if app.selected_alloc > 0 {
|
|
app.selected_alloc--
|
|
}
|
|
}
|
|
.down {
|
|
// Next allocation
|
|
allocs := app.cached_allocs
|
|
if app.selected_alloc < allocs.len - 1 {
|
|
app.selected_alloc++
|
|
}
|
|
}
|
|
.enter {
|
|
// Open source file in editor
|
|
open_in_editor(app)
|
|
}
|
|
.f {
|
|
// Cycle filter modes
|
|
app.filter_mode = match app.filter_mode {
|
|
.all { .new_not_freed }
|
|
.new_not_freed { .large }
|
|
.large { .current_frame }
|
|
.current_frame { .all }
|
|
}
|
|
}
|
|
.r {
|
|
// Reset profiler data
|
|
if !app.demo_mode {
|
|
profiler.reset()
|
|
}
|
|
}
|
|
.escape {
|
|
// Clear selection
|
|
app.selected_frame = -1
|
|
app.selected_alloc = -1
|
|
}
|
|
.space {
|
|
// Toggle demo mode
|
|
app.demo_mode = !app.demo_mode
|
|
if app.demo_mode {
|
|
// Initialize demo data
|
|
init_demo_data(mut app)
|
|
}
|
|
}
|
|
else {}
|
|
}
|
|
}
|
|
|
|
// open_in_editor opens the selected allocation's source file in VS Code
|
|
fn open_in_editor(app &App) {
|
|
if app.selected_alloc < 0 {
|
|
return
|
|
}
|
|
|
|
allocs := app.cached_allocs
|
|
if app.selected_alloc >= allocs.len {
|
|
return
|
|
}
|
|
|
|
alloc := allocs[app.selected_alloc]
|
|
if alloc.file.len == 0 {
|
|
return
|
|
}
|
|
|
|
// Try to open in VS Code with line number
|
|
cmd := 'code -g "${alloc.file}:${alloc.line}"'
|
|
os.execute(cmd)
|
|
}
|