Skip to content

Commit 73090b6

Browse files
committed
improve cursor positioning in mouse selections
1 parent b5baa62 commit 73090b6

File tree

5 files changed

+32
-22
lines changed

5 files changed

+32
-22
lines changed

event_handlers.v

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,6 @@ module gui
66
//
77
import arrays
88

9-
// MouseLockCfg stores callback functions for mouse event handling in a locked state.
10-
// When mouse is locked, these callbacks intercept normal mouse event processing.
11-
// Used for implementing drag operations and modal behaviors.
12-
pub struct MouseLockCfg {
13-
pub:
14-
mouse_down ?fn (&Layout, mut Event, mut Window)
15-
mouse_move ?fn (&Layout, mut Event, mut Window)
16-
mouse_up ?fn (&Layout, mut Event, mut Window)
17-
}
18-
199
fn char_handler(layout &Layout, mut e Event, mut w Window) {
2010
for child in layout.children {
2111
if child.shape.disabled {

examples/multiline_input.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import gui
22

3-
// Multiline Text Demo
3+
// Multiline Input Demo
44
// =============================
55

66
@[heap]
@@ -11,7 +11,7 @@ mut:
1111

1212
fn main() {
1313
mut window := gui.window(
14-
title: 'Multiline Text Test'
14+
title: 'Multiline Input Demo'
1515
state: &MultilineApp{}
1616
width: 400
1717
height: 300

view_state.v

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module gui
22

33
import sokol.sapp
44

5-
// Generating views and immediate mode means there is no place to
6-
// store view states. This is gui's solution.
5+
// Generating views and immediate mode means there is no place to store view
6+
// states. This is v-gui's solution.
77
struct ViewState {
88
mut:
99
input_state map[u32]InputState // [id_focus] -> InputState
@@ -18,12 +18,25 @@ mut:
1818
select_state map[string]bool // [id select] -> open/close state
1919
tree_state map[string]map[string]bool // [tree id] -> [node id ] -> open/closed
2020
date_picker_state map[string]DatePickerState // [id date_picker -> DatePickerState
21-
mouse_lock MouseLockCfg // mouse down/move/up methods to call when locked
21+
mouse_lock MouseLockCfg // mouse down/move/up/scroll/sliders, etc. use this
2222
id_focus u32 // current view that has focus
2323
cursor_on_sticky bool // keeps the cursor visible during cursor movement
2424
input_cursor_on bool = true // used by cursor blink animation
2525
}
2626

27+
// MouseLockCfg stores callback functions for mouse event handling in a locked state.
28+
// When mouse is locked, these callbacks intercept normal mouse event processing.
29+
// Used for implementing drag operations and modal behaviors.
30+
pub struct MouseLockCfg {
31+
pub:
32+
cursor_pos int
33+
mouse_down ?fn (&Layout, mut Event, mut Window)
34+
mouse_move ?fn (&Layout, mut Event, mut Window)
35+
mouse_up ?fn (&Layout, mut Event, mut Window)
36+
}
37+
38+
// clear releases all stored view state maps and resets the window's ViewState.
39+
// Call this when a window is destroyed or needs its GUI state fully reinitialized.
2740
fn (mut vs ViewState) clear(mut w Window) {
2841
unsafe {
2942
vs.input_state.free()

view_text.v

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,10 @@ fn (tv &TextView) on_click(layout &Layout, mut e Event, mut w Window) {
130130
}
131131
if e.mouse_button == .left && w.is_focus(layout.shape.id_focus) {
132132
id_focus := layout.shape.id_focus
133+
cursor_pos := tv.mouse_cursor_pos(layout.shape, e, mut w)
133134
// Init mouse lock to handle dragging selection (mouse move) and finishing selection (mouse up)
134135
w.mouse_lock(
136+
cursor_pos: cursor_pos
135137
mouse_move: fn [tv, id_focus] (layout &Layout, mut e Event, mut w Window) {
136138
// The layout in mouse locks is always the root layout.
137139
if ly := layout.find_layout(fn [id_focus] (ly Layout) bool {
@@ -153,7 +155,6 @@ fn (tv &TextView) on_click(layout &Layout, mut e Event, mut w Window) {
153155
}
154156
)
155157
// Set cursor position and reset text selection
156-
cursor_pos := tv.mouse_cursor_pos(layout.shape, e, mut w)
157158
cursor_offset := offset_from_cursor_position(layout.shape, cursor_pos, w)
158159
input_state := w.view_state.input_state[layout.shape.id_focus]
159160
w.view_state.input_state[layout.shape.id_focus] = InputState{
@@ -181,17 +182,23 @@ fn (tv &TextView) mouse_move_locked(layout &Layout, mut e Event, mut w Window) {
181182
}
182183
ev := event_relative_to(layout.shape, e)
183184
input_state := w.view_state.input_state[layout.shape.id_focus]
184-
cursor_pos := u32(input_state.cursor_pos)
185+
start_cursor_pos := u32(w.view_state.mouse_lock.cursor_pos)
185186
mouse_cursor_pos := u32(tv.mouse_cursor_pos(layout.shape, ev, mut w))
186187

187-
// Update selection range: start is the original cursor pos, end is the current mouse pos
188188
w.view_state.input_state[layout.shape.id_focus] = InputState{
189189
...input_state
190-
select_beg: if cursor_pos < mouse_cursor_pos { cursor_pos } else { mouse_cursor_pos }
191-
select_end: if cursor_pos < mouse_cursor_pos { mouse_cursor_pos } else { cursor_pos }
190+
cursor_pos: int(mouse_cursor_pos)
191+
cursor_offset: -1
192+
select_beg: match start_cursor_pos < mouse_cursor_pos {
193+
true { start_cursor_pos }
194+
else { mouse_cursor_pos }
195+
}
196+
select_end: match start_cursor_pos < mouse_cursor_pos {
197+
true { mouse_cursor_pos }
198+
else { start_cursor_pos }
199+
}
192200
}
193201

194-
// Ensure the cursor being dragged to is visible
195202
scroll_cursor_into_view(int(mouse_cursor_pos), layout, ev, mut w)
196203
e.is_handled = true
197204
}

xtra_window.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn (mut window Window) blinky_cursor_animation() {
2121
}
2222

2323
// color_background returns the window background color
24-
pub fn (window &Window) color_background() Color {
24+
pub fn (_ &Window) color_background() Color {
2525
return gui_theme.color_background
2626
}
2727

0 commit comments

Comments
 (0)