diff --git a/src/message-list/message-layout.vala b/src/message-list/message-layout.vala index 86c66ec..e70a3fe 100644 --- a/src/message-list/message-layout.vala +++ b/src/message-list/message-layout.vala @@ -1,6 +1,24 @@ using Gtk; using Gee; +private struct MessageLayoutConstants { + public float tail_width; + public float tail_curve_offset; + public float tail_side_offset; + public float tail_bottom_padding; + public float corner_radius; + public float text_padding; + + public MessageLayoutConstants(float scale_factor) { + tail_width = 15.0f / scale_factor; + tail_curve_offset = 2.5f / scale_factor; + tail_side_offset = 0.0f / scale_factor; + tail_bottom_padding = 4.0f / scale_factor; + corner_radius = 32.0f / scale_factor; + text_padding = 18.0f / scale_factor; + } +} + private class MessageLayout : Object { public Message message; @@ -8,25 +26,25 @@ private class MessageLayout : Object private float max_width; private Pango.Layout layout; private Widget parent; - - const float tail_width = 15.0f; - const float tail_curve_offset = 2.5f; - const float tail_side_offset = 0.0f; - const float tail_bottom_padding = 4.0f; - const float corner_radius = 32.0f; - const float text_padding = 18.0f; - - const string font_description = "Sans 13"; + private MessageLayoutConstants constants; public MessageLayout(Message message, Widget parent, float max_width) { this.message = message; this.max_width = max_width; this.parent = parent; + this.constants = MessageLayoutConstants(parent.get_scale_factor()); layout = parent.create_pango_layout(message.text); - // Set text attributes - var font_desc = Pango.FontDescription.from_string(font_description); + // Get the system font settings + var settings = Gtk.Settings.get_default(); + var font_name = settings.gtk_font_name; + + // Create font description from system font + var font_desc = Pango.FontDescription.from_string(font_name); + + var size = font_desc.get_size(); + font_desc.set_size((int)(size)); layout.set_font_description(font_desc); // Set max width @@ -41,20 +59,20 @@ private class MessageLayout : Object private float text_available_width { get { - return max_width - text_x_offset - text_padding; + return max_width - text_x_offset - constants.text_padding; } } private float text_x_offset { get { - return from_me ? text_padding : tail_width + text_padding; + return from_me ? constants.text_padding : constants.tail_width + constants.text_padding; } } private float text_x_padding { get { // Opposite of text_x_offset - return from_me ? tail_width + text_padding : text_padding; + return from_me ? constants.tail_width + constants.text_padding : constants.text_padding; } } @@ -73,7 +91,7 @@ private class MessageLayout : Object Pango.Rectangle ink_rect, logical_rect; layout.get_pixel_extents(out ink_rect, out logical_rect); - return logical_rect.height + corner_radius + tail_bottom_padding; + return logical_rect.height + constants.corner_radius + constants.tail_bottom_padding; } public float get_width() { @@ -98,7 +116,7 @@ private class MessageLayout : Object layout.get_pixel_extents(out ink_rect, out logical_rect); snapshot.translate(Graphene.Point() { x = text_x_offset, - y = ((get_height() - tail_bottom_padding) - logical_rect.height) / 2 + y = ((get_height() - constants.tail_bottom_padding) - logical_rect.height) / 2 }); snapshot.append_layout(layout, Gdk.RGBA() { @@ -151,11 +169,11 @@ private class MessageLayout : Object { var builder = new Gsk.PathBuilder(); - float bubble_width = width - tail_width; - float bubble_height = height - tail_bottom_padding; + float bubble_width = width - constants.tail_width; + float bubble_height = height - constants.tail_bottom_padding; // Base position adjustments based on tail position - float x = tail_on_right ? 0.0f : tail_width; + float x = tail_on_right ? 0.0f : constants.tail_width; float y = 0.0f; // Calculate tail direction multiplier (-1 for left, 1 for right) @@ -165,38 +183,38 @@ private class MessageLayout : Object float tail_side_x = tail_on_right ? (x + bubble_width) : x; // Start at top corner opposite to the tail - builder.move_to(tail_on_right ? (x + corner_radius) : (x + bubble_width - corner_radius), y); + builder.move_to(tail_on_right ? (x + constants.corner_radius) : (x + bubble_width - constants.corner_radius), y); // Top edge - builder.line_to(tail_on_right ? (x + bubble_width - corner_radius) : (x + corner_radius), y); + builder.line_to(tail_on_right ? (x + bubble_width - constants.corner_radius) : (x + constants.corner_radius), y); // Top corner on tail side if (tail_on_right) { builder.html_arc_to(x + bubble_width, y, - x + bubble_width, y + corner_radius, - corner_radius); + x + bubble_width, y + constants.corner_radius, + constants.corner_radius); } else { builder.html_arc_to(x, y, - x, y + corner_radius, - corner_radius); + x, y + constants.corner_radius, + constants.corner_radius); } // Side edge on tail side - builder.line_to(tail_side_x, y + bubble_height - corner_radius); + builder.line_to(tail_side_x, y + bubble_height - constants.corner_radius); // Corner with tail - float tail_tip_x = tail_side_x + (dir * (tail_width - tail_curve_offset)); + float tail_tip_x = tail_side_x + (dir * (constants.tail_width - constants.tail_curve_offset)); float tail_tip_y = y + bubble_height; // Control points for the bezier curve - float ctrl_point1_x = tail_side_x + (dir * tail_side_offset); - float ctrl_point1_y = y + bubble_height - corner_radius/3; + float ctrl_point1_x = tail_side_x + (dir * constants.tail_side_offset); + float ctrl_point1_y = y + bubble_height - constants.corner_radius/3; - float ctrl_point2_x = tail_side_x + (dir * (tail_width / 2.0f)); + float ctrl_point2_x = tail_side_x + (dir * (constants.tail_width / 2.0f)); float ctrl_point2_y = y + bubble_height - 2; // Point where the tail meets the bottom edge - float tail_base_x = tail_side_x - (dir * corner_radius/2); + float tail_base_x = tail_side_x - (dir * constants.corner_radius/2); float tail_base_y = y + bubble_height; // Draw the corner with tail using bezier curves @@ -204,39 +222,39 @@ private class MessageLayout : Object ctrl_point2_x, ctrl_point2_y, tail_tip_x, tail_tip_y); - builder.cubic_to(tail_tip_x - (dir * tail_curve_offset), tail_tip_y + tail_curve_offset, - tail_base_x + (dir * tail_width), tail_base_y, + builder.cubic_to(tail_tip_x - (dir * constants.tail_curve_offset), tail_tip_y + constants.tail_curve_offset, + tail_base_x + (dir * constants.tail_width), tail_base_y, tail_base_x, tail_base_y); // Bottom edge - builder.line_to(tail_on_right ? (x + corner_radius) : (x + bubble_width - corner_radius), y + bubble_height); + builder.line_to(tail_on_right ? (x + constants.corner_radius) : (x + bubble_width - constants.corner_radius), y + bubble_height); // Bottom corner opposite to tail if (tail_on_right) { builder.html_arc_to(x, y + bubble_height, - x, y + bubble_height - corner_radius, - corner_radius); + x, y + bubble_height - constants.corner_radius, + constants.corner_radius); } else { builder.html_arc_to(x + bubble_width, y + bubble_height, - x + bubble_width, y + bubble_height - corner_radius, - corner_radius); + x + bubble_width, y + bubble_height - constants.corner_radius, + constants.corner_radius); } // Side edge opposite to tail if (tail_on_right) { - builder.line_to(x, y + corner_radius); + builder.line_to(x, y + constants.corner_radius); // Top corner to close path builder.html_arc_to(x, y, - x + corner_radius, y, - corner_radius); + x + constants.corner_radius, y, + constants.corner_radius); } else { - builder.line_to(x + bubble_width, y + corner_radius); + builder.line_to(x + bubble_width, y + constants.corner_radius); // Top corner to close path builder.html_arc_to(x + bubble_width, y, - x + bubble_width - corner_radius, y, - corner_radius); + x + bubble_width - constants.corner_radius, y, + constants.corner_radius); } // Close the path diff --git a/src/resources/style.css b/src/resources/style.css index bc9a39f..20b65e0 100644 --- a/src/resources/style.css +++ b/src/resources/style.css @@ -1,7 +1,7 @@ /* Kordophone application styles */ .conversation-row { - padding: 8px 12px; + padding: 6px 10px; border-bottom: 1px solid alpha(#000, 0.1); }