Add double click gesture on image bubbles to open
This commit is contained in:
@@ -16,8 +16,9 @@ private class TranscriptDrawingArea : Widget
|
||||
}
|
||||
}
|
||||
|
||||
public signal void on_text_bubble_hover(VisibleTextLayout? text_bubble);
|
||||
public signal void on_text_bubble_click(VisibleTextLayout? text_bubble);
|
||||
public signal void on_text_bubble_hover(VisibleLayout? text_bubble);
|
||||
public signal void on_text_bubble_click(VisibleLayout? text_bubble);
|
||||
public signal void on_image_bubble_activate(string attachment_guid);
|
||||
|
||||
private ArrayList<Message> _messages = new ArrayList<Message>();
|
||||
private ArrayList<ChatItemLayout> _chat_items = new ArrayList<ChatItemLayout>();
|
||||
@@ -29,7 +30,7 @@ private class TranscriptDrawingArea : Widget
|
||||
private Gdk.Rectangle? _click_bounding_box = null;
|
||||
|
||||
private EventControllerMotion _motion_controller = new EventControllerMotion();
|
||||
private ArrayList<VisibleTextLayout?> _visible_text_layouts = new ArrayList<VisibleTextLayout?>();
|
||||
private ArrayList<VisibleLayout?> _visible_text_layouts = new ArrayList<VisibleLayout?>();
|
||||
|
||||
private const bool debug_viewport = false;
|
||||
private uint? _tick_callback_id = null;
|
||||
@@ -41,8 +42,8 @@ private class TranscriptDrawingArea : Widget
|
||||
weak TranscriptDrawingArea self = this;
|
||||
|
||||
_click_gesture.button = 0;
|
||||
_click_gesture.begin.connect(() => {
|
||||
self.on_click(self._click_gesture.get_current_button());
|
||||
_click_gesture.pressed.connect((n_press, x, y) => {
|
||||
self.on_click(self._click_gesture.get_current_button(), n_press);
|
||||
});
|
||||
add_controller(_click_gesture);
|
||||
|
||||
@@ -157,8 +158,8 @@ private class TranscriptDrawingArea : Widget
|
||||
// Skip drawing if this item is not in the viewport
|
||||
float height_offset = 0.0f;
|
||||
if (viewport_rect.intersection(rect, null)) {
|
||||
if (chat_item is TextBubbleLayout) {
|
||||
_visible_text_layouts.add(VisibleTextLayout(chat_item as TextBubbleLayout, rect));
|
||||
if (chat_item is BubbleLayout) {
|
||||
_visible_text_layouts.add(VisibleLayout(chat_item as BubbleLayout, rect));
|
||||
}
|
||||
|
||||
snapshot.save();
|
||||
@@ -199,9 +200,10 @@ private class TranscriptDrawingArea : Widget
|
||||
animation_tick();
|
||||
}
|
||||
|
||||
private VisibleTextLayout? get_text_bubble_at(double x, double y) {
|
||||
private VisibleLayout? get_visible_layout_at(double x, double y) {
|
||||
var point = Graphene.Point() { x = (float)x, y = (float)y };
|
||||
foreach (var layout in _visible_text_layouts) {
|
||||
if (layout.rect.contains_point(Graphene.Point() { x = (float)x, y = (float)y })) {
|
||||
if (layout.rect.contains_point(point)) {
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
@@ -209,16 +211,29 @@ private class TranscriptDrawingArea : Widget
|
||||
return null;
|
||||
}
|
||||
|
||||
private VisibleLayout? get_text_bubble_at(double x, double y) {
|
||||
var layout = get_visible_layout_at(x, y);
|
||||
if (layout != null && layout.bubble is TextBubbleLayout) {
|
||||
return layout;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void on_mouse_motion(double x, double y) {
|
||||
VisibleTextLayout? hovered_text_bubble = get_text_bubble_at(x, y);
|
||||
VisibleLayout? hovered_text_bubble = get_text_bubble_at(x, y);
|
||||
on_text_bubble_hover(hovered_text_bubble);
|
||||
}
|
||||
|
||||
private void on_click(uint button) {
|
||||
private void on_click(uint button, int n_press) {
|
||||
if (button == Gdk.BUTTON_SECONDARY) {
|
||||
on_right_click();
|
||||
} else if (button == Gdk.BUTTON_PRIMARY) {
|
||||
on_left_click();
|
||||
|
||||
if (n_press == 2) {
|
||||
on_double_click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +245,17 @@ private class TranscriptDrawingArea : Widget
|
||||
}
|
||||
}
|
||||
|
||||
private void on_double_click() {
|
||||
Gdk.Rectangle? bounding_box = null;
|
||||
if (_click_gesture.get_bounding_box(out bounding_box)) {
|
||||
var double_clicked_bubble = get_visible_layout_at(bounding_box.x, bounding_box.y);
|
||||
if (double_clicked_bubble != null && double_clicked_bubble.bubble is ImageBubbleLayout) {
|
||||
var image_bubble = double_clicked_bubble.bubble as ImageBubbleLayout;
|
||||
on_image_bubble_activate(image_bubble.attachment_guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void on_right_click() {
|
||||
var menu_model = new Menu();
|
||||
menu_model.append("Copy", "transcript.copy");
|
||||
@@ -346,6 +372,8 @@ private class TranscriptDrawingArea : Widget
|
||||
|
||||
var image_layout = new ImageBubbleLayout(attachment.preview_path, message.from_me, this, max_width, image_size);
|
||||
image_layout.id = @"image-$(attachment.guid)";
|
||||
image_layout.attachment_guid = attachment.guid;
|
||||
|
||||
if (animate) {
|
||||
start_animation(image_layout.id);
|
||||
}
|
||||
@@ -410,12 +438,12 @@ private class ChatItemAnimation
|
||||
}
|
||||
}
|
||||
|
||||
public struct VisibleTextLayout {
|
||||
public weak TextBubbleLayout text_bubble;
|
||||
public struct VisibleLayout {
|
||||
public weak BubbleLayout bubble;
|
||||
public Graphene.Rect rect;
|
||||
|
||||
public VisibleTextLayout(TextBubbleLayout text_bubble, Graphene.Rect rect) {
|
||||
this.text_bubble = text_bubble;
|
||||
public VisibleLayout(BubbleLayout bubble, Graphene.Rect rect) {
|
||||
this.bubble = bubble;
|
||||
this.rect = rect;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user