notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

context_menu.rs (3282B)


      1 /// Context menu helpers (paste, etc)
      2 use egui_winit::clipboard::Clipboard;
      3 
      4 #[derive(Copy, Clone, Eq, PartialEq)]
      5 pub enum PasteBehavior {
      6     Clear,
      7     Append,
      8 }
      9 
     10 fn handle_paste(clipboard: &mut Clipboard, input: &mut String, paste_behavior: PasteBehavior) {
     11     if let Some(text) = clipboard.get() {
     12         // if called with clearing_input_context, then we clear before
     13         // we paste. Useful for certain fields like passwords, etc
     14         match paste_behavior {
     15             PasteBehavior::Clear => input.clear(),
     16             PasteBehavior::Append => {}
     17         }
     18         input.push_str(&text);
     19     }
     20 }
     21 
     22 pub fn input_context(
     23     ui: &mut egui::Ui,
     24     response: &egui::Response,
     25     clipboard: &mut Clipboard,
     26     input: &mut String,
     27     paste_behavior: PasteBehavior,
     28 ) {
     29     response.context_menu(|ui| {
     30         if ui.button("Paste").clicked() {
     31             handle_paste(clipboard, input, paste_behavior);
     32             ui.close_menu();
     33         }
     34 
     35         if ui.button("Copy").clicked() {
     36             clipboard.set_text(input.to_owned());
     37             ui.close_menu();
     38         }
     39 
     40         if ui.button("Cut").clicked() {
     41             clipboard.set_text(input.to_owned());
     42             input.clear();
     43             ui.close_menu();
     44         }
     45     });
     46 
     47     if response.middle_clicked() {
     48         handle_paste(clipboard, input, paste_behavior)
     49     }
     50 
     51     // for keyboard visibility
     52     crate::include_input(ui, response)
     53 }
     54 
     55 pub fn stationary_arbitrary_menu_button<R>(
     56     ui: &mut egui::Ui,
     57     button_response: egui::Response,
     58     add_contents: impl FnOnce(&mut egui::Ui) -> R,
     59 ) -> egui::InnerResponse<Option<R>> {
     60     let bar_id = ui.id();
     61     let mut bar_state = egui::menu::BarState::load(ui.ctx(), bar_id);
     62 
     63     let inner = bar_state.bar_menu(&button_response, add_contents);
     64 
     65     bar_state.store(ui.ctx(), bar_id);
     66     egui::InnerResponse::new(inner.map(|r| r.inner), button_response)
     67 }
     68 
     69 pub fn context_button(ui: &mut egui::Ui, id: egui::Id, put_at: egui::Rect) -> egui::Response {
     70     let min_radius = 2.0;
     71     let anim_speed = 0.05;
     72     let response = ui.interact(put_at, id, egui::Sense::click());
     73 
     74     let hovered = response.hovered();
     75     let animation_progress = ui.ctx().animate_bool_with_time(id, hovered, anim_speed);
     76 
     77     if hovered {
     78         ui.ctx().set_cursor_icon(egui::CursorIcon::PointingHand);
     79     }
     80 
     81     let max_distance = 2.0;
     82     let expansion_mult = 2.0;
     83     let min_distance = max_distance / expansion_mult;
     84     let cur_distance = min_distance + (max_distance - min_distance) * animation_progress;
     85 
     86     let max_radius = 4.0;
     87     let cur_radius = min_radius + (max_radius - min_radius) * animation_progress;
     88 
     89     let center = put_at.center();
     90     let left_circle_center = center - egui::vec2(cur_distance + cur_radius, 0.0);
     91     let right_circle_center = center + egui::vec2(cur_distance + cur_radius, 0.0);
     92 
     93     let translated_radius = (cur_radius - 1.0) / 2.0;
     94 
     95     // This works in both themes
     96     let color = ui.style().visuals.noninteractive().fg_stroke.color;
     97 
     98     // Draw circles
     99     let painter = ui.painter_at(put_at);
    100     painter.circle_filled(left_circle_center, translated_radius, color);
    101     painter.circle_filled(center, translated_radius, color);
    102     painter.circle_filled(right_circle_center, translated_radius, color);
    103 
    104     response
    105 }