diff --git a/src/transcript/transcript-drawing-area.vala b/src/transcript/transcript-drawing-area.vala index e100d27..8a002f7 100644 --- a/src/transcript/transcript-drawing-area.vala +++ b/src/transcript/transcript-drawing-area.vala @@ -22,12 +22,37 @@ private class TranscriptDrawingArea : Widget private Adjustment? _viewport = null; private const float bubble_margin = 18.0f; + private GestureClick _click_gesture = new GestureClick(); + private Gdk.Rectangle? _click_bounding_box = null; + private const bool debug_viewport = false; private uint? _tick_callback_id = null; private HashMap _animations = new HashMap(); public TranscriptDrawingArea() { add_css_class("transcript-drawing-area"); + + weak TranscriptDrawingArea self = this; + + _click_gesture.button = Gdk.BUTTON_SECONDARY; + _click_gesture.begin.connect(() => { + self.on_right_click(); + }); + add_controller(_click_gesture); + + SimpleAction copy_action = new SimpleAction("copy", null); + copy_action.activate.connect(() => { + if (_click_bounding_box != null) { + copy_message_at(_click_bounding_box); + } else { + GLib.warning("Failed to get bounding box for right click"); + } + }); + + SimpleActionGroup action_group = new SimpleActionGroup(); + action_group.add_action(copy_action); + + insert_action_group("transcript", action_group); } public void set_messages(ArrayList messages) { @@ -147,6 +172,39 @@ private class TranscriptDrawingArea : Widget animation_tick(); } + private void on_right_click() { + var menu_model = new Menu(); + menu_model.append("Copy", "transcript.copy"); + + Gdk.Rectangle? bounding_box = null; + if (_click_gesture.get_bounding_box(out bounding_box)) { + _click_bounding_box = bounding_box; + + var menu = new PopoverMenu.from_model(menu_model); + menu.set_position(PositionType.TOP); + menu.pointing_to = bounding_box; + menu.set_parent(this); + menu.popup(); + } + } + + private void copy_message_at(Gdk.Rectangle bounding_box) { + double y_offset = 0.0; + for (int i = _chat_items.size - 1; i >= 0; i--) { + var chat_item = _chat_items[i]; + y_offset += chat_item.get_height() + chat_item.vertical_padding; + + if (y_offset > bounding_box.y) { + var text_bubble = chat_item as TextBubbleLayout; + var text = text_bubble.message.text; + + var clipboard = get_clipboard(); + clipboard.set_text(text); + break; + } + } + } + private bool animation_tick() { HashSet animations_to_remove = new HashSet(); _animations.foreach(entry => {