fix issue with grep/buffer window not changing position on window resize

rust-rewrite
Patrick Cleavelin 2024-01-27 13:26:29 -06:00
parent ccfdc2e325
commit 8d63375838
7 changed files with 195 additions and 151 deletions

View File

@ -222,6 +222,7 @@ type UiRectProc = extern "C" fn(
ui_context: UiContext, ui_context: UiContext,
label: *const i8, label: *const i8,
border: bool, border: bool,
border: bool,
axis: UiAxis, axis: UiAxis,
size: [InternalUiSemanticSize; 2], size: [InternalUiSemanticSize; 2],
) -> UiBox; ) -> UiBox;
@ -235,6 +236,7 @@ pub struct UiVTable {
push_parent: UiPushParentProc, push_parent: UiPushParentProc,
pop_parent: UiPopParentProc, pop_parent: UiPopParentProc,
spacer: UiSimpleProc,
floating: UiFloatingProc, floating: UiFloatingProc,
rect: UiRectProc, rect: UiRectProc,
@ -253,9 +255,14 @@ impl UiVTable {
(self.pop_parent)(self.ui_context); (self.pop_parent)(self.ui_context);
} }
pub fn spacer(&self, label: &CStr) -> UiInteraction {
(self.spacer)(self.ui_context, label.as_ptr())
}
pub fn push_rect( pub fn push_rect(
&self, &self,
label: &CStr, label: &CStr,
show_background: bool,
show_border: bool, show_border: bool,
axis: UiAxis, axis: UiAxis,
horizontal_size: UiSemanticSize, horizontal_size: UiSemanticSize,
@ -265,6 +272,7 @@ impl UiVTable {
let rect = (self.rect)( let rect = (self.rect)(
self.ui_context, self.ui_context,
label.as_ptr(), label.as_ptr(),
show_background,
show_border, show_border,
axis, axis,
[horizontal_size.into(), vertical_size.into()], [horizontal_size.into(), vertical_size.into()],

View File

@ -109,44 +109,54 @@ draw_buffer_window :: proc "c" (plugin: Plugin, win: rawptr) {
screen_height := plugin.get_screen_height(); screen_height := plugin.get_screen_height();
directory := string(plugin.get_current_directory()); directory := string(plugin.get_current_directory());
canvas := plugin.ui.floating(plugin.ui.ui_context, "buffer search canvas", {screen_width/8, screen_height/8}); canvas := plugin.ui.floating(plugin.ui.ui_context, "buffer search canvas", {0,0});
plugin.ui.push_parent(plugin.ui.ui_context, canvas); plugin.ui.push_parent(plugin.ui.ui_context, canvas);
{ {
defer plugin.ui.pop_parent(plugin.ui.ui_context); defer plugin.ui.pop_parent(plugin.ui.ui_context);
ui_window := plugin.ui.rect(plugin.ui.ui_context, "buffer search window", true, .Horizontal, {{4, 75}, {4, 75}}); plugin.ui.spacer(plugin.ui.ui_context, "left spacer");
plugin.ui.push_parent(plugin.ui.ui_context, ui_window); centered_container := plugin.ui.rect(plugin.ui.ui_context, "centered container", false, false, .Vertical, {{4, 75}, {3, 0}});
plugin.ui.push_parent(plugin.ui.ui_context, centered_container);
{ {
defer plugin.ui.pop_parent(plugin.ui.ui_context); defer plugin.ui.pop_parent(plugin.ui.ui_context);
buffer_list_view := plugin.ui.rect(plugin.ui.ui_context, "buffer list view", false, .Vertical, {{4, 60}, {3, 0}}); plugin.ui.spacer(plugin.ui.ui_context, "top spacer");
plugin.ui.push_parent(plugin.ui.ui_context, buffer_list_view); ui_window := plugin.ui.rect(plugin.ui.ui_context, "buffer search window", true, true, .Horizontal, {{3, 0}, {4, 75}});
plugin.ui.push_parent(plugin.ui.ui_context, ui_window);
{ {
defer plugin.ui.pop_parent(plugin.ui.ui_context); defer plugin.ui.pop_parent(plugin.ui.ui_context);
_buffer_index := 0; buffer_list_view := plugin.ui.rect(plugin.ui.ui_context, "buffer list view", false, false, .Vertical, {{4, 60}, {3, 0}});
for index in buffer_list_iter(plugin, &_buffer_index) { plugin.ui.push_parent(plugin.ui.ui_context, buffer_list_view);
buffer := plugin.buffer.get_buffer_info_from_index(index); {
relative_file_path, _ := filepath.rel(directory, string(buffer.file_path), context.temp_allocator) defer plugin.ui.pop_parent(plugin.ui.ui_context);
text := fmt.ctprintf("%s:%d", relative_file_path, buffer.cursor.line+1);
if index == win.selected_index { _buffer_index := 0;
plugin.ui.button(plugin.ui.ui_context, text); for index in buffer_list_iter(plugin, &_buffer_index) {
} else { buffer := plugin.buffer.get_buffer_info_from_index(index);
plugin.ui.label(plugin.ui.ui_context, text); relative_file_path, _ := filepath.rel(directory, string(buffer.file_path), context.temp_allocator)
text := fmt.ctprintf("%s:%d", relative_file_path, buffer.cursor.line+1);
if index == win.selected_index {
plugin.ui.button(plugin.ui.ui_context, text);
} else {
plugin.ui.label(plugin.ui.ui_context, text);
}
} }
} }
}
buffer_preview := plugin.ui.rect(plugin.ui.ui_context, "buffer preview", false, .Horizontal, {{3, 0}, {3, 0}}); buffer_preview := plugin.ui.rect(plugin.ui.ui_context, "buffer preview", true, false, .Horizontal, {{3, 0}, {3, 0}});
plugin.ui.push_parent(plugin.ui.ui_context, buffer_preview); plugin.ui.push_parent(plugin.ui.ui_context, buffer_preview);
{ {
defer plugin.ui.pop_parent(plugin.ui.ui_context); defer plugin.ui.pop_parent(plugin.ui.ui_context);
plugin.ui.buffer_from_index(plugin.ui.ui_context, win.selected_index, false); plugin.ui.buffer_from_index(plugin.ui.ui_context, win.selected_index, false);
}
} }
plugin.ui.spacer(plugin.ui.ui_context, "bottom spacer");
} }
plugin.ui.spacer(plugin.ui.ui_context, "right spacer");
} }
/* /*

View File

@ -281,134 +281,130 @@ extern "C" fn draw_window(plugin: Plugin, window: *const std::ffi::c_void) {
let dir = plugin.get_current_directory(); let dir = plugin.get_current_directory();
let directory = Path::new(dir.as_ref()); let directory = Path::new(dir.as_ref());
plugin.ui_table.push_floating( plugin
c"grep canvas", .ui_table
(screen_width as isize) / 8, .push_floating(c"grep canvas", 0, 0, |ui_table| {
(screen_height as isize) / 8, // TODO: make some primitive that centers a Box
|ui_table| { ui_table.spacer(c"left spacer");
ui_table.push_rect( ui_table.push_rect(
c"grep window", c"centered container",
true, false,
false,
UiAxis::Vertical, UiAxis::Vertical,
UiSemanticSize::PercentOfParent(75), UiSemanticSize::PercentOfParent(75),
UiSemanticSize::PercentOfParent(75), UiSemanticSize::Fill,
|ui_table| { |ui_table| {
if let Ok(sink) = window.rx.try_recv() { ui_table.spacer(c"top spacer");
window.sink = Some(sink);
}
ui_table.push_rect(
c"results list",
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| match &window.sink {
Some(sink) if !sink.matches.is_empty() => {
let num_mats_to_draw = std::cmp::min(
(sink.matches.len() - window.top_index) as i32,
(height - font_height) / (font_height),
);
for (i, mat) in sink.matches[window.top_index..].iter().enumerate()
{
let index = i + window.top_index;
if i as i32 >= num_mats_to_draw {
break;
}
let path = Path::new(&mat.path);
let relative_file_path = path
.strip_prefix(directory)
.unwrap_or(path)
.to_str()
.unwrap_or("");
let matched_text = String::from_utf8_lossy(&mat.text);
let text = match mat.line_number {
Some(line_number) => format!(
"{}:{}:{}: {}",
relative_file_path,
line_number,
mat.column,
matched_text
),
None => format!(
"{}:{}: {}",
relative_file_path, mat.column, matched_text
),
};
if index == window.selected_match {
ui_table.button(&CString::new(text).expect("valid text"));
} else {
ui_table.label(&CString::new(text).expect("valid text"));
}
}
}
Some(_) | None => {
ui_table.push_rect(
c"top spacer",
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {},
);
ui_table.push_rect(
c"centered text container",
false,
UiAxis::Horizontal,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {
ui_table.push_rect(
c"left spacer",
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {},
);
ui_table.label(c"no results");
ui_table.push_rect(
c"right spacer",
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {},
);
},
);
ui_table.push_rect(
c"bottom spacer",
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {},
);
}
},
);
ui_table.push_rect( ui_table.push_rect(
c"grep window", c"grep window",
false, true,
true,
UiAxis::Vertical, UiAxis::Vertical,
UiSemanticSize::Fill, UiSemanticSize::Fill,
UiSemanticSize::Exact(font_height as isize), UiSemanticSize::PercentOfParent(75),
|ui_table| { |ui_table| {
if let Some(buffer) = window.input_buffer { if let Ok(sink) = window.rx.try_recv() {
ui_table.buffer(buffer, false); window.sink = Some(sink);
} }
ui_table.push_rect(
c"results list",
false,
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| match &window.sink {
Some(sink) if !sink.matches.is_empty() => {
let num_mats_to_draw = std::cmp::min(
(sink.matches.len() - window.top_index) as i32,
(height - font_height) / (font_height),
);
for (i, mat) in
sink.matches[window.top_index..].iter().enumerate()
{
let index = i + window.top_index;
if i as i32 >= num_mats_to_draw {
break;
}
let path = Path::new(&mat.path);
let relative_file_path = path
.strip_prefix(directory)
.unwrap_or(path)
.to_str()
.unwrap_or("");
let matched_text = String::from_utf8_lossy(&mat.text);
let text = match mat.line_number {
Some(line_number) => format!(
"{}:{}:{}: {}",
relative_file_path,
line_number,
mat.column,
matched_text
),
None => format!(
"{}:{}: {}",
relative_file_path, mat.column, matched_text
),
};
if index == window.selected_match {
// TODO: don't use button here, but apply a style
// to `label`
ui_table.button(
&CString::new(text).expect("valid text"),
);
} else {
ui_table.label(
&CString::new(text).expect("valid text"),
);
}
}
}
Some(_) | None => {
ui_table.spacer(c"top spacer");
ui_table.push_rect(
c"centered text container",
false,
false,
UiAxis::Horizontal,
UiSemanticSize::Fill,
UiSemanticSize::Fill,
|ui_table| {
ui_table.spacer(c"left spacer");
ui_table.label(c"no results");
ui_table.spacer(c"right spacer");
},
);
ui_table.spacer(c"bottom spacer");
}
},
);
ui_table.push_rect(
c"grep window",
true,
false,
UiAxis::Vertical,
UiSemanticSize::Fill,
UiSemanticSize::Exact(font_height as isize),
|ui_table| {
if let Some(buffer) = window.input_buffer {
ui_table.buffer(buffer, false);
}
},
);
}, },
); );
ui_table.spacer(c"bottom spacer");
}, },
); );
}, ui_table.spacer(c"right spacer");
); });
} }
extern "C" fn on_buffer_input(plugin: Plugin, buffer: Buffer) { extern "C" fn on_buffer_input(plugin: Plugin, buffer: Buffer) {

View File

@ -49,6 +49,8 @@ State :: struct {
should_close: bool, should_close: bool,
screen_height: int, screen_height: int,
screen_width: int, screen_width: int,
width_dpi_ratio: f32,
height_dpi_ratio: f32,
directory: string, directory: string,

View File

@ -194,6 +194,7 @@ register_default_input_actions :: proc(input_map: ^core.InputMap) {
core.register_key_action(input_map, .A, proc(state: ^State) { core.register_key_action(input_map, .A, proc(state: ^State) {
core.move_cursor_right(&state.buffers[state.current_buffer], false); core.move_cursor_right(&state.buffers[state.current_buffer], false);
state.mode = .Insert; state.mode = .Insert;
sdl2.StartTextInput();
}, "enter insert mode after character (append)"); }, "enter insert mode after character (append)");
} }
@ -341,6 +342,9 @@ expose_event_watcher :: proc "c" (state: rawptr, event: ^sdl2.Event) -> i32 {
state.state.screen_width = int(w); state.state.screen_width = int(w);
state.state.screen_height = int(h); state.state.screen_height = int(h);
state.state.width_dpi_ratio = f32(w) / f32(event.window.data1);
state.state.height_dpi_ratio = f32(h) / f32(event.window.data2);
draw(state); draw(state);
} }
} }
@ -870,6 +874,18 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
ui.pop_parent(ui_context); ui.pop_parent(ui_context);
}, },
spacer = proc "c" (ui_context: rawptr, label: cstring) -> plugin.UiInteraction {
context = state.ctx;
ui_context := transmute(^ui.Context)ui_context;
label := strings.clone(string(label), context.temp_allocator);
interaction := ui.spacer(ui_context, label);
return plugin.UiInteraction {
hovering = interaction.hovering,
clicked = interaction.clicked,
};
},
// TODO: allow this to have more flags sent to it // TODO: allow this to have more flags sent to it
floating = proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> plugin.UiBox { floating = proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> plugin.UiBox {
context = state.ctx; context = state.ctx;
@ -878,7 +894,7 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
return ui.push_floating(ui_context, label, pos); return ui.push_floating(ui_context, label, pos);
}, },
rect = proc "c" (ui_context: rawptr, label: cstring, border: bool, axis: plugin.UiAxis, size: [2]plugin.UiSemanticSize) -> plugin.UiBox { rect = proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: plugin.UiAxis, size: [2]plugin.UiSemanticSize) -> plugin.UiBox {
context = state.ctx; context = state.ctx;
ui_context := transmute(^ui.Context)ui_context; ui_context := transmute(^ui.Context)ui_context;
label := strings.clone(string(label), context.temp_allocator); label := strings.clone(string(label), context.temp_allocator);
@ -894,7 +910,7 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
}, },
}; };
return ui.push_rect(ui_context, label, border, ui.Axis(axis), size); return ui.push_rect(ui_context, label, background, border, ui.Axis(axis), size);
}, },
label = proc "c" (ui_context: rawptr, label: cstring) -> plugin.UiInteraction { label = proc "c" (ui_context: rawptr, label: cstring) -> plugin.UiInteraction {
@ -944,8 +960,10 @@ init_plugin_vtable :: proc(ui_context: ^ui.Context) -> plugin.Plugin {
main :: proc() { main :: proc() {
state = State { state = State {
ctx = context, ctx = context,
source_font_width = 8 + 2 * 3, screen_width = 640,
source_font_height = 16 + 2 * 3, screen_height = 480,
source_font_width = 8,
source_font_height = 16,
input_map = core.new_input_map(), input_map = core.new_input_map(),
window = nil, window = nil,
directory = os.get_current_directory(), directory = os.get_current_directory(),
@ -984,7 +1002,7 @@ main :: proc() {
0, 0,
640, 640,
480, 480,
{.SHOWN, .RESIZABLE, .METAL, .ALLOW_HIGHDPI} {.SHOWN, .RESIZABLE, .ALLOW_HIGHDPI}
); );
defer if sdl_window != nil { defer if sdl_window != nil {
sdl2.DestroyWindow(sdl_window); sdl2.DestroyWindow(sdl_window);
@ -1014,6 +1032,17 @@ main :: proc() {
} }
} }
{
w,h: i32;
sdl2.GetRendererOutputSize(state.sdl_renderer, &w, &h);
state.width_dpi_ratio = f32(w) / f32(state.screen_width);
state.height_dpi_ratio = f32(h) / f32(state.screen_height);
state.screen_width = int(w);
state.screen_height = int(h);
}
// Done to clear the buffer
sdl2.StartTextInput(); sdl2.StartTextInput();
sdl2.StopTextInput(); sdl2.StopTextInput();
@ -1031,11 +1060,7 @@ main :: proc() {
} }
} }
control_key_pressed: bool; control_key_pressed: bool;
state.screen_width = 640; //int(raylib.GetScreenWidth());
state.screen_height = 480; //int(raylib.GetScreenHeight());
for !state.should_close { for !state.should_close {
{ {
buffer := &state.buffers[state.current_buffer]; buffer := &state.buffers[state.current_buffer];
@ -1162,8 +1187,8 @@ main :: proc() {
} }
if sdl_event.type == .MOUSEMOTION { if sdl_event.type == .MOUSEMOTION {
ui_context.mouse_x = int(sdl_event.motion.x); ui_context.mouse_x = int(f32(sdl_event.motion.x) * state.width_dpi_ratio);
ui_context.mouse_y = int(sdl_event.motion.y); ui_context.mouse_y = int(f32(sdl_event.motion.y) * state.height_dpi_ratio);
} }
if sdl_event.type == .MOUSEBUTTONDOWN || sdl_event.type == .MOUSEBUTTONUP { if sdl_event.type == .MOUSEBUTTONDOWN || sdl_event.type == .MOUSEBUTTONUP {

View File

@ -105,7 +105,7 @@ UiPushParentProc :: proc "c" (ui_context: rawptr, box: UiBox);
UiPopParentProc :: proc "c" (ui_context: rawptr); UiPopParentProc :: proc "c" (ui_context: rawptr);
UiFloatingProc :: proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> UiBox; UiFloatingProc :: proc "c" (ui_context: rawptr, label: cstring, pos: [2]int) -> UiBox;
UiCreateBoxProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiBox; UiCreateBoxProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiBox;
UiRectProc :: proc "c" (ui_context: rawptr, label: cstring, border: bool, axis: UiAxis, size: [2]UiSemanticSize) -> UiBox; UiRectProc :: proc "c" (ui_context: rawptr, label: cstring, background: bool, border: bool, axis: UiAxis, size: [2]UiSemanticSize) -> UiBox;
UiSimpleProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiInteraction; UiSimpleProc :: proc "c" (ui_context: rawptr, label: cstring) -> UiInteraction;
UiBufferProc :: proc "c" (ui_context: rawptr, buffer: rawptr, show_line_numbers: bool); UiBufferProc :: proc "c" (ui_context: rawptr, buffer: rawptr, show_line_numbers: bool);
UiBufferIndexProc :: proc "c" (ui_context: rawptr, buffer: int, show_line_numbers: bool); UiBufferIndexProc :: proc "c" (ui_context: rawptr, buffer: int, show_line_numbers: bool);
@ -115,6 +115,7 @@ Ui :: struct {
push_parent: UiPushParentProc, push_parent: UiPushParentProc,
pop_parent: UiPopParentProc, pop_parent: UiPopParentProc,
spacer: UiSimpleProc,
floating: UiFloatingProc, floating: UiFloatingProc,
rect: UiRectProc, rect: UiRectProc,

View File

@ -672,19 +672,21 @@ debug_print :: proc(ctx: ^Context, box: ^Box, depth: int = 0) {
} }
} }
spacer :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {}, semantic_size: [2]SemanticSize = {{.Fill, 0}, {.Fill,0}}) -> ^Box { spacer :: proc(ctx: ^Context, label: string, flags: bit_set[Flag] = {}, semantic_size: [2]SemanticSize = {{.Fill, 0}, {.Fill,0}}) -> Interaction {
return push_box(ctx, label, flags, semantic_size = semantic_size); box := push_box(ctx, label, flags, semantic_size = semantic_size);
return test_box(ctx, box);
} }
push_floating :: proc(ctx: ^Context, label: string, pos: [2]int, flags: bit_set[Flag] = {.Floating}, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> ^Box { push_floating :: proc(ctx: ^Context, label: string, pos: [2]int, flags: bit_set[Flag] = {.Floating}, axis: Axis = .Horizontal, semantic_size: [2]SemanticSize = Fill) -> ^Box {
box := push_box(ctx, label, flags, semantic_size = semantic_size); box := push_box(ctx, label, flags, semantic_size = semantic_size);
box.computed_pos = pos; box.computed_pos = pos;
return box; return box;
} }
push_rect :: proc(ctx: ^Context, label: string, border: bool = true, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> ^Box { push_rect :: proc(ctx: ^Context, label: string, background: bool = true, border: bool = true, axis: Axis = .Vertical, semantic_size: [2]SemanticSize = Fill) -> ^Box {
return push_box(ctx, label, {.DrawBackground, .DrawBorder if border else nil}, axis, semantic_size = semantic_size); return push_box(ctx, label, {.DrawBackground if background else nil, .DrawBorder if border else nil}, axis, semantic_size = semantic_size);
} }
label :: proc(ctx: ^Context, label: string) -> Interaction { label :: proc(ctx: ^Context, label: string) -> Interaction {