Private
Public Access
1
0
Files
Kordophone/src/transcript/transcript-drawing-area.vala

124 lines
4.1 KiB
Vala
Raw Normal View History

2025-04-30 19:12:00 -07:00
using Gtk;
using Gee;
2025-05-03 22:47:56 -07:00
private class TranscriptDrawingArea : Widget
2025-04-30 19:12:00 -07:00
{
2025-05-03 23:19:15 -07:00
public bool show_sender = true;
2025-04-30 19:12:00 -07:00
private SortedSet<Message> _messages = new TreeSet<Message>();
private ArrayList<ChatItemLayout> _chat_items = new ArrayList<ChatItemLayout>();
2025-04-30 19:12:00 -07:00
private const float bubble_margin = 18.0f;
2025-05-03 22:47:56 -07:00
public TranscriptDrawingArea() {
add_css_class("transcript-drawing-area");
2025-04-30 19:12:00 -07:00
}
public void set_messages(SortedSet<Message> messages) {
_messages = messages;
recompute_message_layouts();
}
public override SizeRequestMode get_request_mode() {
return SizeRequestMode.HEIGHT_FOR_WIDTH;
}
public override void measure(Orientation orientation, int for_size, out int minimum, out int natural, out int minimum_baseline, out int natural_baseline)
{
if (orientation == Orientation.HORIZONTAL) {
// Horizontal, so we take up the full width provided
minimum = 0;
natural = for_size;
} else {
// compute total message layout height
float total_height = 0.0f;
_chat_items.foreach((chat_item) => {
2025-05-03 23:19:15 -07:00
total_height += chat_item.get_height() + chat_item.vertical_padding;
2025-04-30 19:12:00 -07:00
return true;
});
minimum = (int)total_height;
natural = (int)total_height;
}
minimum_baseline = -1;
natural_baseline = -1;
}
public override void size_allocate(int width, int height, int baseline) {
base.size_allocate(width, height, baseline);
recompute_message_layouts();
}
public override void snapshot(Snapshot snapshot) {
float y_offset = 0;
2025-05-03 23:19:15 -07:00
var container_width = get_width();
// Draw each item in reverse order, since the messages are in reverse order
for (int i = _chat_items.size - 1; i >= 0; i--) {
var chat_item = _chat_items[i];
2025-05-03 22:41:51 -07:00
var item_width = chat_item.get_width();
var item_height = chat_item.get_height();
2025-04-30 19:12:00 -07:00
snapshot.save();
// Flip the y-axis, since our parent is upside down (so newest messages are at the bottom)
snapshot.scale(1.0f, -1.0f);
// Translate to the correct position
snapshot.translate(Graphene.Point() {
2025-05-03 22:41:51 -07:00
x = (chat_item.from_me ? (container_width - item_width - bubble_margin) : bubble_margin),
2025-04-30 19:12:00 -07:00
y = y_offset
});
// Undo the y-axis flip, origin is top left
2025-05-03 22:41:51 -07:00
snapshot.translate(Graphene.Point() { x = 0, y = -item_height });
2025-04-30 19:12:00 -07:00
chat_item.draw(snapshot);
2025-04-30 19:12:00 -07:00
snapshot.restore();
2025-05-03 23:19:15 -07:00
y_offset -= item_height + chat_item.vertical_padding;
}
2025-04-30 19:12:00 -07:00
}
private void recompute_message_layouts() {
var container_width = get_width();
float max_width = container_width * 0.90f;
2025-05-03 22:41:51 -07:00
DateTime? last_date = null;
2025-05-03 23:19:15 -07:00
string? last_sender = null;
ArrayList<ChatItemLayout> items = new ArrayList<ChatItemLayout>();
_messages.foreach((message) => {
// Date Annotation
DateTime date = message.date;
2025-05-04 00:17:50 -07:00
if (last_date != null && date.difference(last_date) > (TimeSpan.HOUR * 1)) {
2025-05-03 23:19:15 -07:00
var date_item = new DateItemLayout(date.to_local().format("%b %d, %Y at %H:%M"), this, max_width);
items.add(date_item);
last_date = date;
}
// Sender Annotation
if (show_sender && !message.from_me && last_sender != message.sender) {
var sender_bubble = new SenderAnnotationLayout(message.sender, max_width, this);
items.add(sender_bubble);
2025-05-03 22:41:51 -07:00
}
2025-05-03 23:19:15 -07:00
// Text Bubble
2025-05-03 22:41:51 -07:00
var text_bubble = new TextBubbleLayout(message, this, max_width);
2025-05-03 23:19:15 -07:00
text_bubble.vertical_padding = (last_sender == message.sender) ? 0.0f : 10.0f;
items.add(text_bubble);
last_sender = message.sender;
last_date = date;
2025-04-30 19:12:00 -07:00
return true;
});
2025-05-03 23:19:15 -07:00
_chat_items.clear();
_chat_items.add_all(items);
2025-04-30 19:12:00 -07:00
queue_draw();
2025-04-30 19:50:36 -07:00
queue_resize();
2025-04-30 19:12:00 -07:00
}
2025-05-04 00:17:50 -07:00
}