[gnome-builder/wip/gtk4-port] plugins/omni-gutter: prototype selections in gutter
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port] plugins/omni-gutter: prototype selections in gutter
- Date: Fri, 29 Apr 2022 23:18:30 +0000 (UTC)
commit 5d8fe515610fbfb5de88887ab6ec091c927acf30
Author: Christian Hergert <chergert redhat com>
Date: Fri Apr 29 16:18:26 2022 -0700
plugins/omni-gutter: prototype selections in gutter
src/plugins/omni-gutter/gbp-omni-gutter-renderer.c | 123 +++++++++++++++++----
1 file changed, 101 insertions(+), 22 deletions(-)
---
diff --git a/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
index fb63bb921..28dec478a 100644
--- a/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
+++ b/src/plugins/omni-gutter/gbp-omni-gutter-renderer.c
@@ -92,7 +92,7 @@ struct _GbpOmniGutterRenderer
GdkRGBA fg;
GdkRGBA bg;
gboolean bold;
- } text, current, bkpt, ctpt;
+ } text, current, bkpt, ctpt, sel;
GdkRGBA stopped_bg;
struct {
GdkRGBA add;
@@ -160,6 +160,11 @@ struct _GbpOmniGutterRenderer
/* Delayed reload timeout source */
guint reload_source;
+ /* Cached information for drawing */
+ double draw_width;
+ double draw_width_with_margin;
+ guint draw_has_focus : 1;
+
/*
* Some users might want to toggle off individual features of the
* omni gutter, and these boolean properties provide that. Other
@@ -230,6 +235,7 @@ G_DEFINE_FINAL_TYPE_WITH_CODE (GbpOmniGutterRenderer,
G_IMPLEMENT_INTERFACE (IDE_TYPE_GUTTER, gutter_iface_init))
static GParamSpec *properties [N_PROPS];
+static GQuark selection_quark;
static PangoAttrList *bold_attrs;
static int
@@ -451,6 +457,12 @@ reload_style_colors (GbpOmniGutterRenderer *self,
context = gtk_widget_get_style_context (GTK_WIDGET (view));
gtk_style_context_get_color (context, &fg);
+ if (!get_style_rgba (scheme, "selection", FOREGROUND, &self->sel.fg))
+ gtk_style_context_lookup_color (context, "theme_selected_fg_color", &self->sel.fg);
+
+ if (!get_style_rgba (scheme, "selection", BACKGROUND, &self->sel.bg))
+ gtk_style_context_lookup_color (context, "theme_selected_bg_color", &self->sel.bg);
+
/* Extract common values from style schemes. */
if (!get_style_rgba (scheme, "line-numbers", FOREGROUND, &self->text.fg))
self->text.fg = fg;
@@ -827,10 +839,11 @@ gbp_omni_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
IdeSourceView *view;
GtkTextTag *tag;
GtkTextIter bkpt;
- GtkTextIter begin;
- GtkTextIter end;
+ GtkTextIter begin, end;
+ GtkTextIter sel_begin, sel_end;
guint end_line;
int width;
+ int left_margin;
g_assert (GBP_IS_OMNI_GUTTER_RENDERER (renderer));
g_assert (lines != NULL);
@@ -845,7 +858,14 @@ gbp_omni_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
self->stopped_line = -1;
+ view = IDE_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+ left_margin = gtk_text_view_get_left_margin (GTK_TEXT_VIEW (view));
width = gtk_widget_get_width (GTK_WIDGET (self));
+
+ self->draw_width = width;
+ self->draw_width_with_margin = width + left_margin;
+ self->draw_has_focus = gtk_widget_has_focus (GTK_WIDGET (view));
+
self->begin_line = gtk_source_gutter_lines_get_first (lines);
end_line = gtk_source_gutter_lines_get_last (lines);
@@ -864,14 +884,41 @@ gbp_omni_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
self->stopped_line = gtk_text_iter_get_line (&bkpt);
}
+ /* Add quark for line selections which will display all the way to the
+ * left margin so that we can draw selection borders (rounded corners
+ * which extend under the line numbers).
+ */
+ if (gtk_text_buffer_get_selection_bounds (buffer, &sel_begin, &sel_end))
+ {
+ int first_sel = -1, last_sel = -1;
+
+ gtk_text_iter_order (&sel_begin, &sel_end);
+
+ if (gtk_text_iter_starts_line (&sel_begin))
+ first_sel = gtk_text_iter_get_line (&sel_begin);
+ else if (gtk_text_iter_get_line (&sel_begin) != gtk_text_iter_get_line (&sel_end))
+ first_sel = gtk_text_iter_get_line (&sel_begin) + 1;
+
+ if (!gtk_text_iter_starts_line (&sel_end))
+ last_sel = gtk_text_iter_get_line (&sel_end);
+ else if (gtk_text_iter_get_line (&sel_begin) != gtk_text_iter_get_line (&sel_end))
+ last_sel = gtk_text_iter_get_line (&sel_end) - 1;
+
+ if (first_sel != -1 && last_sel != -1)
+ {
+ first_sel = MAX (first_sel, gtk_source_gutter_lines_get_first (lines));
+ last_sel = MIN (last_sel, gtk_source_gutter_lines_get_last (lines));
+
+ for (int i = first_sel; i <= last_sel; i++)
+ gtk_source_gutter_lines_add_qclass (lines, i, selection_quark);
+ }
+ }
+
/*
* This function is called before we render any of the lines in
* the gutter. To reduce our overhead, we want to collect information
* for all of the line numbers upfront.
*/
-
- view = IDE_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
-
ide_source_view_get_visual_position (view, &self->cursor_line, NULL);
/* Give ourselves a fresh array to stash our line info */
@@ -996,6 +1043,32 @@ gbp_omni_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
IDE_EXIT;
}
+static void
+draw_selection_bg (GbpOmniGutterRenderer *self,
+ GtkSnapshot *snapshot,
+ double line_y,
+ double width,
+ double height,
+ gboolean is_first_line,
+ gboolean is_last_last)
+{
+ GskRoundedRect rounded_rect;
+
+ rounded_rect = GSK_ROUNDED_RECT_INIT (2, line_y, width - 2, height);
+
+ if (is_first_line)
+ rounded_rect.corner[0] = GRAPHENE_SIZE_INIT (9, 9);
+
+ if (is_last_last)
+ rounded_rect.corner[3] = GRAPHENE_SIZE_INIT (9, 9);
+
+ gtk_snapshot_push_rounded_clip (snapshot, &rounded_rect);
+ gtk_snapshot_append_color (snapshot,
+ &self->sel.bg,
+ &GRAPHENE_RECT_INIT (2, line_y, width - 2, height));
+ gtk_snapshot_pop (snapshot);
+}
+
static void
draw_breakpoint_bg (GbpOmniGutterRenderer *self,
GtkSnapshot *snapshot,
@@ -1112,7 +1185,6 @@ gbp_omni_gutter_renderer_snapshot_line (GtkSourceGutterRenderer *renderer,
{
GbpOmniGutterRenderer *self = (GbpOmniGutterRenderer *)renderer;
GtkSourceView *view;
- gboolean has_focus;
gboolean highlight_line;
int line_y;
int line_height;
@@ -1131,10 +1203,9 @@ gbp_omni_gutter_renderer_snapshot_line (GtkSourceGutterRenderer *renderer,
view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
highlight_line = gtk_source_view_get_highlight_current_line (GTK_SOURCE_VIEW (view));
- has_focus = gtk_widget_has_focus (GTK_WIDGET (view));
gtk_source_gutter_lines_get_line_yrange (lines, line, GTK_SOURCE_GUTTER_RENDERER_ALIGNMENT_MODE_CELL,
&line_y, &line_height);
- width = gtk_widget_get_width (GTK_WIDGET (renderer));
+ width = self->draw_width;
if ((line - self->begin_line) < self->lines->len)
{
@@ -1143,6 +1214,15 @@ gbp_omni_gutter_renderer_snapshot_line (GtkSourceGutterRenderer *renderer,
gboolean has_breakpoint = FALSE;
gboolean bold = FALSE;
+ /* Draw our selection edges which overlap the gutter */
+ if (gtk_source_gutter_lines_has_qclass (lines, line, selection_quark))
+ {
+ gboolean is_first = line == 0 || line == gtk_source_gutter_lines_get_first (lines) ||
!gtk_source_gutter_lines_has_qclass (lines, line - 1, selection_quark);
+ gboolean is_last = line == gtk_source_gutter_lines_get_last (lines) ||
!gtk_source_gutter_lines_has_qclass (lines, line + 1, selection_quark);
+
+ draw_selection_bg (self, snapshot, line_y, self->draw_width_with_margin, line_height, is_first,
is_last);
+ }
+
/*
* Draw some background for the line so that it looks like the
* breakpoint arrow draws over it. Debugger break line takes
@@ -1153,7 +1233,7 @@ gbp_omni_gutter_renderer_snapshot_line (GtkSourceGutterRenderer *renderer,
gtk_snapshot_append_color (snapshot,
&self->stopped_bg,
&GRAPHENE_RECT_INIT (0, line_y, width, line_height));
- else if (highlight_line && has_focus && gtk_source_gutter_lines_is_cursor (lines, line))
+ else if (highlight_line && self->draw_has_focus && gtk_source_gutter_lines_is_cursor (lines, line))
gtk_snapshot_append_color (snapshot,
&self->current.bg,
&GRAPHENE_RECT_INIT (0, line_y, width, line_height));
@@ -1384,26 +1464,23 @@ static void
gbp_omni_gutter_renderer_cursor_moved (GbpOmniGutterRenderer *self,
GtkTextBuffer *buffer)
{
- GtkTextMark *mark;
GtkTextIter iter;
+ GtkTextMark *insert;
guint line;
g_assert (GBP_IS_OMNI_GUTTER_RENDERER (self));
g_assert (IDE_IS_BUFFER (buffer));
- mark = gtk_text_buffer_get_insert (buffer);
- gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+ insert = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
line = gtk_text_iter_get_line (&iter);
- if (line != self->last_cursor_line)
- {
- self->last_cursor_line = line;
- gtk_widget_queue_draw (GTK_WIDGET (self));
- }
- else if (self->show_relative_line_numbers)
- {
- gtk_widget_queue_draw (GTK_WIDGET (self));
- }
+ if (line != self->last_cursor_line ||
+ self->show_relative_line_numbers ||
+ gtk_text_buffer_get_has_selection (buffer))
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+
+ self->last_cursor_line = line;
}
static void
@@ -1577,6 +1654,8 @@ gbp_omni_gutter_renderer_class_init (GbpOmniGutterRendererClass *klass)
bold_attrs = pango_attr_list_new ();
pango_attr_list_insert (bold_attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+
+ selection_quark = g_quark_from_static_string ("omni-selection");
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]