| ... | @@ -46,6 +46,9 @@ pub enum Action { | ... | @@ -46,6 +46,9 @@ pub enum Action { |
| 46 | Options, | 46 | Options, |
| 47 | /// A row's context menu, opened here. | 47 | /// A row's context menu, opened here. |
| 48 | Menu(Target, [f32; 2]), | 48 | Menu(Target, [f32; 2]), |
| | 49 | /// Opens the rename field on a row double-clicked, folding back by `Library::key` the |
| | 50 | /// row its first click folded. |
| | 51 | Rename(rename::Target, Option<String>), |
| 49 | /// Ends renaming, with the name typed or without. | 52 | /// Ends renaming, with the name typed or without. |
| 50 | Renamed(bool), | 53 | Renamed(bool), |
| 51 | /// Explains why a section or group can't be opened: the alert's title and message. | 54 | /// Explains why a section or group can't be opened: the alert's title and message. |
| ... | @@ -212,6 +215,7 @@ fn sidebar( | ... | @@ -212,6 +215,7 @@ fn sidebar( |
| 212 | for (index, library) in notebooks.iter().enumerate() { | 215 | for (index, library) in notebooks.iter().enumerate() { |
| 213 | let key = library.key(""); | 216 | let key = library.key(""); |
| 214 | let unfolded = !folded.contains(&key); | 217 | let unfolded = !folded.contains(&key); |
| | 218 | let renamed = (tree.renaming.as_ref()).is_some_and(|renaming| renaming.notebook(library)); |
| 215 | let (row, fold) = tree_row( | 219 | let (row, fold) = tree_row( |
| 216 | ui, | 220 | ui, |
| 217 | tree, | 221 | tree, |
| ... | @@ -230,7 +234,7 @@ fn sidebar( | ... | @@ -230,7 +234,7 @@ fn sidebar( |
| 230 | dim: library.notebook.is_err(), | 234 | dim: library.notebook.is_err(), |
| 231 | fold: Some(unfolded), | 235 | fold: Some(unfolded), |
| 232 | selected: None, | 236 | selected: None, |
| 233 | renamed: false, | 237 | renamed, |
| 234 | bold: tree.unread.contains(&key), | 238 | bold: tree.unread.contains(&key), |
| 235 | }, | 239 | }, |
| 236 | ); | 240 | ); |
| ... | @@ -238,7 +242,10 @@ fn sidebar( | ... | @@ -238,7 +242,10 @@ fn sidebar( |
| 238 | && crate::library::server_address(&library.location).is_some(); | 242 | && crate::library::server_address(&library.location).is_some(); |
| 239 | if row.clicked && unsigned { | 243 | if row.clicked && unsigned { |
| 240 | tree.action = Some(Action::SignIn(library.location.clone())); | 244 | tree.action = Some(Action::SignIn(library.location.clone())); |
| 241 | } else if row.clicked || fold { | 245 | } else if double(&row) && library.catalog().is_some() { |
| | 246 | let target = rename::Target::Notebook(Arc::clone(library)); |
| | 247 | tree.action = Some(Action::Rename(target, Some(key))); |
| | 248 | } else if row.clicked && !renamed || fold { |
| 242 | tree.action = Some(Action::Fold(key)); | 249 | tree.action = Some(Action::Fold(key)); |
| 243 | } | 250 | } |
| 244 | if let Some(point) = row.context { | 251 | if let Some(point) = row.context { |
| ... | @@ -365,7 +372,14 @@ fn folder( | ... | @@ -365,7 +372,14 @@ fn folder( |
| 365 | continue; | 372 | continue; |
| 366 | } | 373 | } |
| 367 | let (row, _) = tree_row(ui, tree, id, row); | 374 | let (row, _) = tree_row(ui, tree, id, row); |
| 368 | if row.clicked && readable && open != Some(section.path.as_str()) { | 375 | if double(&row) && readable { |
| | 376 | let target = rename::Target::Entry { |
| | 377 | library: Arc::clone(library), |
| | 378 | path: section.path.clone(), |
| | 379 | in_tab: false, |
| | 380 | }; |
| | 381 | tree.action = Some(Action::Rename(target, None)); |
| | 382 | } else if row.clicked && readable && open != Some(section.path.as_str()) { |
| 369 | tree.action = Some(Action::Open { | 383 | tree.action = Some(Action::Open { |
| 370 | notebook, | 384 | notebook, |
| 371 | path: section.path.clone(), | 385 | path: section.path.clone(), |
| ... | @@ -405,7 +419,14 @@ fn folder( | ... | @@ -405,7 +419,14 @@ fn folder( |
| 405 | let lifted = lifts(tree, notebook, &group.path, &row); | 419 | let lifted = lifts(tree, notebook, &group.path, &row); |
| 406 | if !lifted { | 420 | if !lifted { |
| 407 | let (row, fold) = tree_row(ui, tree, id, row); | 421 | let (row, fold) = tree_row(ui, tree, id, row); |
| 408 | if row.clicked || fold { | 422 | if double(&row) { |
| | 423 | let target = rename::Target::Entry { |
| | 424 | library: Arc::clone(library), |
| | 425 | path: group.path.clone(), |
| | 426 | in_tab: false, |
| | 427 | }; |
| | 428 | tree.action = Some(Action::Rename(target, Some(key))); |
| | 429 | } else if row.clicked && !renaming || fold { |
| 409 | tree.action = Some(Action::Fold(key)); | 430 | tree.action = Some(Action::Fold(key)); |
| 410 | } | 431 | } |
| 411 | entry(ui, tree, notebook, &group.path, id, true, &row); | 432 | entry(ui, tree, notebook, &group.path, id, true, &row); |
| ... | @@ -476,6 +497,11 @@ fn folder( | ... | @@ -476,6 +497,11 @@ fn folder( |
| 476 | } | 497 | } |
| 477 | } | 498 | } |
| 478 | | 499 | |
| | 500 | /// Whether `row` was pressed a second time in a double click, which renames it in place. |
| | 501 | fn double(row: &Signal) -> bool { |
| | 502 | row.pressed && row.unit != draw::edit::SelectionUnit::Grapheme |
| | 503 | } |
| | 504 | |
| 479 | /// Where the row `lifted` lands with the pointer at height `y` among `rows`: onto a | 505 | /// Where the row `lifted` lands with the pointer at height `y` among `rows`: onto a |
| 480 | /// group's middle, into it; above or below a row's middle, before or after it in its | 506 | /// group's middle, into it; above or below a row's middle, before or after it in its |
| 481 | /// folder; into another folder, at its end. | 507 | /// folder; into another folder, at its end. |
| ... | @@ -849,6 +875,14 @@ impl crate::State { | ... | @@ -849,6 +875,14 @@ impl crate::State { |
| 849 | self.menu = Some((target, point)); | 875 | self.menu = Some((target, point)); |
| 850 | self.ui.open_popup(crate::menus::id()); | 876 | self.ui.open_popup(crate::menus::id()); |
| 851 | } | 877 | } |
| | 878 | Some(Action::Rename(target, refold)) => { |
| | 879 | if let Some(key) = refold |
| | 880 | && !self.folded.remove(&key) |
| | 881 | { |
| | 882 | self.folded.insert(key); |
| | 883 | } |
| | 884 | self.rename(target); |
| | 885 | } |
| 852 | Some(Action::Renamed(keep)) => self.finish_renaming(keep), | 886 | Some(Action::Renamed(keep)) => self.finish_renaming(keep), |
| 853 | Some(Action::NewNotebook) => self.commands.push(crate::Command::NewNotebook), | 887 | Some(Action::NewNotebook) => self.commands.push(crate::Command::NewNotebook), |
| 854 | Some(Action::OpenNotebook) => self.commands.push(crate::Command::OpenNotebook), | 888 | Some(Action::OpenNotebook) => self.commands.push(crate::Command::OpenNotebook), |