|
19 | 19 | use async_trait::async_trait; |
20 | 20 | use darkfi_money_contract::model::{DARK_TOKEN_ID, TokenId}; |
21 | 21 | use darkfi_serial::{Decodable, Encodable, SerialEncodable}; |
22 | | -use miniquad::MouseButton; |
| 22 | +use miniquad::{MouseButton, TouchPhase}; |
23 | 23 | use parking_lot::Mutex as SyncMutex; |
24 | 24 | use rand::{rngs::OsRng, Rng}; |
25 | 25 | use std::sync::{Arc, Weak}; |
@@ -64,6 +64,7 @@ pub struct TokenTable { |
64 | 64 | node: SceneNodeWeak, |
65 | 65 | renderer: Renderer, |
66 | 66 | sg_root: SceneNodePtr, |
| 67 | + mouse_btn_token: SyncMutex<Option<TokenId>>, |
67 | 68 |
|
68 | 69 | rows: SyncMutex<Vec<TokenRow>>, |
69 | 70 | dc_key: u64, |
@@ -104,6 +105,7 @@ impl TokenTable { |
104 | 105 | node: node.clone(), |
105 | 106 | renderer: renderer.clone(), |
106 | 107 | sg_root, |
| 108 | + mouse_btn_token: SyncMutex::new(None), |
107 | 109 | rows: SyncMutex::new(vec![]), |
108 | 110 | dc_key: OsRng.gen(), |
109 | 111 | rect, |
@@ -370,19 +372,73 @@ impl UIObject for TokenTable { |
370 | 372 | } |
371 | 373 |
|
372 | 374 | if let Some(row) = self.get_row_at_y(mouse_pos.y) { |
373 | | - let mut data = vec![]; |
374 | | - if let Err(e) = row.encode(&mut data) { |
375 | | - error!(target: "ui::tokentable", "Failed to encode row: {e}"); |
376 | | - return false |
377 | | - } |
378 | | - |
379 | | - let node_ref = self.node.upgrade().unwrap(); |
380 | | - let _ = node_ref.trigger("row_click", data).await; |
| 375 | + *self.mouse_btn_token.lock() = Some(row.id); |
381 | 376 | return true |
382 | 377 | } |
383 | 378 |
|
384 | 379 | false |
385 | 380 | } |
| 381 | + |
| 382 | + async fn handle_mouse_btn_up(&self, btn: MouseButton, mouse_pos: Point) -> bool { |
| 383 | + if btn != MouseButton::Left { |
| 384 | + return false |
| 385 | + } |
| 386 | + |
| 387 | + let token_held = { |
| 388 | + let mut mouse_lock = self.mouse_btn_token.lock(); |
| 389 | + let token_held = *mouse_lock; |
| 390 | + *mouse_lock = None; |
| 391 | + token_held |
| 392 | + }; |
| 393 | + |
| 394 | + let Some(token_held) = token_held else { |
| 395 | + return false |
| 396 | + }; |
| 397 | + |
| 398 | + let rect = self.rect.get(); |
| 399 | + if !rect.contains(mouse_pos) { |
| 400 | + return false |
| 401 | + } |
| 402 | + |
| 403 | + let Some(row) = self.get_row_at_y(mouse_pos.y) else { |
| 404 | + return false |
| 405 | + }; |
| 406 | + |
| 407 | + if row.id != token_held { |
| 408 | + return false |
| 409 | + } |
| 410 | + |
| 411 | + let mut data = vec![]; |
| 412 | + if let Err(e) = row.encode(&mut data) { |
| 413 | + error!(target: "ui::tokentable", "Failed to encode row: {e}"); |
| 414 | + return false |
| 415 | + } |
| 416 | + |
| 417 | + let node_ref = self.node.upgrade().unwrap(); |
| 418 | + let _ = node_ref.trigger("row_click", data).await; |
| 419 | + |
| 420 | + true |
| 421 | + } |
| 422 | + |
| 423 | + async fn handle_touch(&self, phase: TouchPhase, id: u64, touch_pos: Point) -> bool { |
| 424 | + // Ignore multi-touch |
| 425 | + if id != 0 { |
| 426 | + return false |
| 427 | + } |
| 428 | + |
| 429 | + let rect = self.rect.get(); |
| 430 | + if !rect.contains(touch_pos) { |
| 431 | + return false |
| 432 | + } |
| 433 | + |
| 434 | + // Simulate mouse events |
| 435 | + match phase { |
| 436 | + TouchPhase::Started => self.handle_mouse_btn_down(MouseButton::Left, touch_pos).await, |
| 437 | + TouchPhase::Moved => false, |
| 438 | + TouchPhase::Ended => self.handle_mouse_btn_up(MouseButton::Left, touch_pos).await, |
| 439 | + TouchPhase::Cancelled => false, |
| 440 | + } |
| 441 | + } |
386 | 442 | } |
387 | 443 |
|
388 | 444 | impl Drop for TokenTable { |
|
0 commit comments