implement bubble view
This commit is contained in:
96
src/message-list/message-drawing-area.vala
Normal file
96
src/message-list/message-drawing-area.vala
Normal file
@@ -0,0 +1,96 @@
|
||||
using Gtk;
|
||||
using Gee;
|
||||
|
||||
private class MessageDrawingArea : Widget
|
||||
{
|
||||
private SortedSet<Message> _messages = new TreeSet<Message>();
|
||||
private ArrayList<MessageLayout> _message_layouts = new ArrayList<MessageLayout>();
|
||||
|
||||
private const float bubble_padding = 10.0f;
|
||||
private const float bubble_margin = 18.0f;
|
||||
|
||||
public MessageDrawingArea() {
|
||||
add_css_class("message-drawing-area");
|
||||
}
|
||||
|
||||
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;
|
||||
_message_layouts.foreach((message_layout) => {
|
||||
total_height += message_layout.get_height() + bubble_padding;
|
||||
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) {
|
||||
var container_width = get_width();
|
||||
float y_offset = 0;
|
||||
_message_layouts.foreach((message_layout) => {
|
||||
var message_width = message_layout.get_width();
|
||||
var message_height = message_layout.get_height();
|
||||
|
||||
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() {
|
||||
x = (message_layout.from_me ? (container_width - message_width - bubble_margin) : bubble_margin),
|
||||
y = y_offset
|
||||
});
|
||||
|
||||
// Undo the y-axis flip, origin is top left
|
||||
snapshot.translate(Graphene.Point() { x = 0, y = -message_height });
|
||||
|
||||
message_layout.draw(snapshot);
|
||||
snapshot.restore();
|
||||
|
||||
y_offset -= message_height + bubble_padding;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void recompute_message_layouts() {
|
||||
var container_width = get_width();
|
||||
float max_width = container_width * 0.90f;
|
||||
|
||||
_message_layouts.clear();
|
||||
_messages
|
||||
.order_by((a, b) => (int)b.date - (int)a.date) // reverse order
|
||||
.foreach((message) => {
|
||||
_message_layouts.add(new MessageLayout(message, this, max_width));
|
||||
return true;
|
||||
});
|
||||
|
||||
queue_draw();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user