Skip to content
This repository was archived by the owner on Jul 27, 2023. It is now read-only.

Commit 9c24f18

Browse files
authored
Fix Viewport update bug (#45)
* Add pending notifications queue The viewport isn't being properly updated, which partially is caused by notifications being dropped when the view-id isn't known. - Added a queue of pending notifications to the EditView struct - Drain the queue and send to core once the view-id is received. - Update the viewport with the calculated size in `Widget`::layout * Zorch viewport on new view Also moving invalidation around. The invalidation changes were included as they affect the UX in a similar way.
1 parent da066f9 commit 9c24f18

File tree

1 file changed

+57
-58
lines changed

1 file changed

+57
-58
lines changed

src/edit_view.rs

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::cmp::min;
1818
use std::ops::Range;
1919
use std::any::Any;
2020
use std::sync::{Mutex, Weak};
21+
use std::mem;
2122

2223
use serde_json::Value;
2324

@@ -59,16 +60,20 @@ pub enum EditViewCommands {
5960
SelectAll,
6061
}
6162

63+
type Method = String;
64+
type Params = Value;
65+
6266
/// State and behavior for one editor view.
6367
pub struct EditView {
64-
view_id: String,
68+
view_id: Option<String>,
6569
line_cache: LineCache,
6670
dwrite_factory: directwrite::Factory,
6771
resources: Option<Resources>,
6872
scroll_offset: f32,
6973
size: (f32, f32), // in px units
7074
viewport: Range<usize>,
7175
core: Weak<Mutex<Core>>,
76+
pending: Vec<(Method, Params)>,
7277
}
7378

7479
struct Resources {
@@ -116,7 +121,10 @@ impl Widget for EditView {
116121
fn layout(&mut self, bc: &BoxConstraints, _children: &[Id], _size: Option<(f32, f32)>,
117122
_ctx: &mut LayoutCtx) -> LayoutResult
118123
{
119-
LayoutResult::Size(bc.constrain((0.0, 0.0)))
124+
let size = bc.constrain((0.0, 0.0));
125+
self.size = size;
126+
self.update_viewport();
127+
LayoutResult::Size(size)
120128
}
121129

122130
fn mouse(&mut self, event: &MouseEvent, _ctx: &mut HandlerCtx) -> bool {
@@ -137,13 +145,24 @@ impl Widget for EditView {
137145
if let Some(cmd) = payload.downcast_ref::<EditViewCommands>() {
138146
match cmd {
139147
EditViewCommands::ViewId(view_id) => {
140-
self.view_id = view_id.to_string();
148+
self.view_id = Some(view_id.to_string());
149+
self.viewport = 0..0; // zorch viewport
150+
self.update_viewport();
151+
152+
// Fire off the pending notifications
153+
let pending = mem::replace(&mut self.pending, Vec::new());
154+
for notification in pending {
155+
let (method, params) = notification;
156+
self.send_edit_cmd(&method, &params);
157+
}
141158
}
142159
EditViewCommands::ApplyUpdate(update) => {
143160
self.apply_update(&update);
161+
ctx.invalidate();
144162
}
145163
EditViewCommands::ScrollTo(line) => {
146164
self.scroll_to(*line);
165+
ctx.invalidate();
147166
}
148167
EditViewCommands::Core(core) => {
149168
self.core = core.clone();
@@ -164,48 +183,55 @@ impl Widget for EditView {
164183
self.send_action("transpose");
165184
}
166185
EditViewCommands::AddCursorAbove => {
167-
self.add_cursor_above();
186+
// Note: some subtlety around find, the escape key cancels it, but the menu
187+
// shouldn't.
188+
self.send_action("add_selection_above");
168189
}
169190
EditViewCommands::AddCursorBelow => {
170-
self.add_cursor_below();
191+
// Note: some subtlety around find, the escape key cancels it, but the menu
192+
// shouldn't.
193+
self.send_action("add_selection_below");
171194
}
172195
EditViewCommands::SingleSelection => {
173-
self.single_selection();
196+
// Note: some subtlety around find, the escape key cancels it, but the menu
197+
// shouldn't.
198+
self.send_action("cancel_operation");
174199
}
175200
EditViewCommands::SelectAll => {
176-
self.select_all();
201+
// Note: some subtlety around find, the escape key cancels it, but the menu
202+
// shouldn't.
203+
self.send_action("select_all");
177204
}
178205
}
179-
// TODO: Finer grained invalidation
180-
ctx.invalidate();
181206
}
182207
true
183208
}
184209

185-
fn key(&mut self, event: &KeyEvent, _ctx: &mut HandlerCtx) -> bool {
210+
fn key(&mut self, event: &KeyEvent, ctx: &mut HandlerCtx) -> bool {
186211
match event.key {
187212
KeyVariant::Vkey(vk) => {
188-
self.keydown(vk, event.mods);
213+
return self.keydown(vk, event.mods, ctx)
189214
}
190215
KeyVariant::Char(ch) => {
191216
self.char(ch as u32, event.mods);
192217
}
193-
}
218+
}
194219
true
195220
}
196221
}
197222

198223
impl EditView {
199224
pub fn new() -> EditView {
200225
EditView {
201-
view_id: "".into(),
226+
view_id: Default::default(),
202227
line_cache: LineCache::new(),
203228
dwrite_factory: directwrite::Factory::new().unwrap(),
204229
resources: None,
205230
scroll_offset: 0.0,
206231
size: (0.0, 0.0),
207232
viewport: 0..0,
208233
core: Default::default(),
234+
pending: Default::default(),
209235
}
210236
}
211237

@@ -232,11 +258,6 @@ impl EditView {
232258
self.resources = None;
233259
}
234260

235-
pub fn size(&mut self, x: f32, y: f32) {
236-
self.size = (x, y);
237-
self.constrain_scroll();
238-
}
239-
240261
pub fn clear_line_cache(&mut self) {
241262
self.line_cache = LineCache::new();
242263
}
@@ -254,7 +275,7 @@ impl EditView {
254275
self.constrain_scroll();
255276
}
256277

257-
pub fn char(&self, ch: u32, _mods: u32) {
278+
pub fn char(&mut self, ch: u32, _mods: u32) {
258279
if let Some(c) = ::std::char::from_u32(ch) {
259280
if ch >= 0x20 {
260281
// Don't insert control characters
@@ -264,34 +285,35 @@ impl EditView {
264285
}
265286
}
266287

267-
fn send_edit_cmd(&self, method: &str, params: &Value) {
268-
let edit_params = json!({
269-
"method": method,
270-
"params": params,
271-
"view_id": &self.view_id,
272-
});
273-
self.send_notification("edit", &edit_params);
274-
}
288+
fn send_edit_cmd(&mut self, method: &str, params: &Value) {
289+
// TODO: When let_chains lands, this will be easier.
290+
let core = self.core.upgrade();
291+
if core.is_some() && self.view_id.is_some() {
292+
let view_id = &self.view_id.clone().unwrap();
293+
let edit_params = json!({
294+
"method": method,
295+
"params": params,
296+
"view_id": view_id,
297+
});
275298

276-
fn send_notification(&self, method: &str, params: &Value) {
277-
if let Some(ref core) = self.core.upgrade() {
278-
core.lock().unwrap().send_notification(method, params);
299+
let core = core.unwrap();
300+
core.lock().unwrap().send_notification("edit", &edit_params);
279301
// NOTE: For debugging, could be replaced by trace logging
280302
// println!("fe->core: {}", json!({
281303
// "method": method,
282304
// "params": params,
283305
// }));
284306
} else {
285-
// TODO: queue pending
307+
self.pending.push((method.to_owned(), params.clone()));
286308
}
287309
}
288310

289311
/// Sends a simple action with no parameters
290-
fn send_action(&self, method: &str) {
312+
fn send_action(&mut self, method: &str) {
291313
self.send_edit_cmd(method, &json!([]));
292314
}
293315

294-
pub fn keydown(&mut self, vk_code: i32, mods: u32) -> bool {
316+
pub fn keydown(&mut self, vk_code: i32, mods: u32, ctx: &mut HandlerCtx) -> bool {
295317
// Handle special keys here
296318
match vk_code {
297319
VK_RETURN => {
@@ -307,6 +329,7 @@ impl EditView {
307329
self.scroll_offset -= LINE_SPACE;
308330
self.constrain_scroll();
309331
self.update_viewport();
332+
ctx.invalidate();
310333
} else {
311334
let action = if mods == M_CTRL | M_ALT {
312335
"add_selection_above"
@@ -322,6 +345,7 @@ impl EditView {
322345
self.scroll_offset += LINE_SPACE;
323346
self.constrain_scroll();
324347
self.update_viewport();
348+
ctx.invalidate();
325349
} else {
326350
let action = if mods == M_CTRL | M_ALT {
327351
"add_selection_below"
@@ -421,31 +445,6 @@ impl EditView {
421445
true
422446
}
423447

424-
// Commands
425-
pub fn add_cursor_above(&mut self) {
426-
// Note: some subtlety around find, the escape key cancels it, but the menu
427-
// shouldn't.
428-
self.send_action("add_selection_above");
429-
}
430-
431-
pub fn add_cursor_below(&mut self) {
432-
// Note: some subtlety around find, the escape key cancels it, but the menu
433-
// shouldn't.
434-
self.send_action("add_selection_below");
435-
}
436-
437-
pub fn single_selection(&mut self) {
438-
// Note: some subtlety around find, the escape key cancels it, but the menu
439-
// shouldn't.
440-
self.send_action("cancel_operation");
441-
}
442-
443-
pub fn select_all(&mut self) {
444-
// Note: some subtlety around find, the escape key cancels it, but the menu
445-
// shouldn't.
446-
self.send_action("select_all");
447-
}
448-
449448
pub fn mouse_wheel(&mut self, delta: i32, _mods: u32) {
450449
// TODO: scale properly, taking SPI_GETWHEELSCROLLLINES into account
451450
let scroll_scaling = 0.5;

0 commit comments

Comments
 (0)