示例#1
0
gboolean
gui_editor_is_marked (GUIEditor * self, gint ln)
{
  GtkTextIter line_start, line_end;
  GSList *list_iter;

  /* get line bounds */
  gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (self->buffer), &line_start, ln);
  line_end = line_start;
  gtk_text_iter_forward_to_line_end (&line_end);

  /* get the markers already in the line */
  list_iter = gtk_source_buffer_get_source_marks_at_iter (self->buffer, &line_start, NULL);

  /* search for the breakpoint marker */
  while (list_iter != NULL)
	{
	  GtkSourceMark *tmp = list_iter->data;
	  const gchar *tmp_type = gtk_source_mark_get_category (tmp);
	  if (tmp_type && !strcmp (tmp_type, MARKER_BREAKPOINT))
		{
		  return TRUE;
		}
	  list_iter = g_slist_next (list_iter);
	}

  return FALSE;
}
static gint
sort_marks_by_priority (gconstpointer m1,
			gconstpointer m2,
			gpointer data)
{
	GtkSourceMark *mark1 = GTK_SOURCE_MARK (m1);
	GtkSourceMark *mark2 = GTK_SOURCE_MARK (m2);
	GtkSourceView *view = GTK_SOURCE_VIEW (data);
	GtkTextIter iter1, iter2;
	gint line1;
	gint line2;

	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark1)),
	                                  &iter1,
	                                  GTK_TEXT_MARK (mark1));

	gtk_text_buffer_get_iter_at_mark (gtk_text_mark_get_buffer (GTK_TEXT_MARK (mark2)),
	                                  &iter2,
	                                  GTK_TEXT_MARK (mark2));

	line1 = gtk_text_iter_get_line (&iter1);
	line2 = gtk_text_iter_get_line (&iter2);

	if (line1 == line2)
	{
		gint priority1 = -1;
		gint priority2 = -1;

		gtk_source_view_get_mark_attributes (view,
		                                     gtk_source_mark_get_category (mark1),
		                                     &priority1);

		gtk_source_view_get_mark_attributes (view,
		                                     gtk_source_mark_get_category (mark2),
		                                     &priority2);

		return priority1 - priority2;
	}
	else
	{
		return line2 - line1;
	}
}
static void
gtk_source_mark_get_property (GObject    *object,
			      guint       prop_id,
			      GValue     *value,
			      GParamSpec *pspec)
{
	GtkSourceMark *mark;

	g_return_if_fail (GTK_IS_SOURCE_MARK (object));

	mark = GTK_SOURCE_MARK (object);

	switch (prop_id)
	{
		case PROP_CATEGORY:
			g_value_set_string (value,
					    gtk_source_mark_get_category (mark));
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
							   prop_id,
							   pspec);
	}
}
static GdkPixbuf *
composite_marks (GtkSourceView *view,
                 GSList        *marks,
                 gint           size)
{
	GdkPixbuf *composite;
	gint mark_width;
	gint mark_height;

	/* Draw the mark with higher priority */
	marks = g_slist_sort_with_data (marks, sort_marks_by_priority, view);

	composite = NULL;
	mark_width = 0;
	mark_height = 0;

	/* composite all the pixbufs for the marks present at the line */
	do
	{
		GtkSourceMark *mark;
		GtkSourceMarkAttributes *attrs;
		const GdkPixbuf *pixbuf;

		mark = marks->data;
		attrs = gtk_source_view_get_mark_attributes (view,
		                                             gtk_source_mark_get_category (mark),
		                                             NULL);

		if (attrs == NULL)
		{
			continue;
		}

		pixbuf = gtk_source_mark_attributes_render_icon (attrs,
		                                                 GTK_WIDGET (view),
		                                                 size);

		if (pixbuf != NULL)
		{
			if (composite == NULL)
			{
				composite = gdk_pixbuf_copy (pixbuf);
				mark_width = gdk_pixbuf_get_width (composite);
				mark_height = gdk_pixbuf_get_height (composite);
			}
			else
			{
				gint pixbuf_w;
				gint pixbuf_h;

				pixbuf_w = gdk_pixbuf_get_width (pixbuf);
				pixbuf_h = gdk_pixbuf_get_height (pixbuf);

				gdk_pixbuf_composite (pixbuf,
				                      composite,
				                      0, 0,
				                      mark_width, mark_height,
				                      0, 0,
				                      (gdouble) pixbuf_w / mark_width,
				                      (gdouble) pixbuf_h / mark_height,
				                      GDK_INTERP_BILINEAR,
				                      COMPOSITE_ALPHA);
			}
		}

		marks = g_slist_next (marks);
	}
	while (marks);

	return composite;
}
static gboolean
set_tooltip_widget_from_marks (GtkSourceView *view,
                               GtkTooltip    *tooltip,
                               GSList        *marks)
{
	GtkGrid *grid = NULL;
	gint row_num = 0;
	gint icon_size;

	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_size);

	for (; marks; marks = g_slist_next (marks))
	{
		const gchar *category;
		GtkSourceMark *mark;
		GtkSourceMarkAttributes *attrs;
		gchar *text;
		gboolean ismarkup = FALSE;
		GtkWidget *label;
		const GdkPixbuf *pixbuf;

		mark = marks->data;
		category = gtk_source_mark_get_category (mark);

		attrs = gtk_source_view_get_mark_attributes (view, category, NULL);

		if (attrs == NULL)
		{
			continue;
		}

		text = gtk_source_mark_attributes_get_tooltip_markup (attrs, mark);

		if (text == NULL)
		{
			text = gtk_source_mark_attributes_get_tooltip_text (attrs, mark);
		}
		else
		{
			ismarkup = TRUE;
		}

		if (text == NULL)
		{
			continue;
		}

		if (grid == NULL)
		{
			grid = GTK_GRID (gtk_grid_new ());
			gtk_grid_set_column_spacing (grid, 4);
			gtk_widget_show (GTK_WIDGET (grid));
		}

		label = gtk_label_new (NULL);

		if (ismarkup)
		{
			gtk_label_set_markup (GTK_LABEL (label), text);
		}
		else
		{
			gtk_label_set_text (GTK_LABEL (label), text);
		}

		gtk_widget_set_halign (label, GTK_ALIGN_START);
		gtk_widget_set_valign (label, GTK_ALIGN_START);
		gtk_widget_show (label);

		pixbuf = gtk_source_mark_attributes_render_icon (attrs,
		                                                 GTK_WIDGET (view),
		                                                 icon_size);

		if (pixbuf == NULL)
		{
			gtk_grid_attach (grid, label, 0, row_num, 2, 1);
		}
		else
		{
			GtkWidget *image;
			GdkPixbuf *copy;

			/* FIXME why a copy is needed? */
			copy = gdk_pixbuf_copy (pixbuf);
			image = gtk_image_new_from_pixbuf (copy);
			g_object_unref (copy);

			gtk_widget_set_halign (image, GTK_ALIGN_START);
			gtk_widget_set_valign (image, GTK_ALIGN_START);
			gtk_widget_show (image);

			gtk_grid_attach (grid, image, 0, row_num, 1, 1);
			gtk_grid_attach (grid, label, 1, row_num, 1, 1);
		}

		row_num++;

		if (marks->next != NULL)
		{
			GtkWidget *separator;

			separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);

			gtk_widget_show (separator);

			gtk_grid_attach (grid, separator, 0, row_num, 2, 1);
			row_num++;
		}

		g_free (text);
	}

	if (grid == NULL)
	{
		return FALSE;
	}

	gtk_tooltip_set_custom (tooltip, GTK_WIDGET (grid));

	return TRUE;
}
static gboolean
set_tooltip_widget_from_marks (GtkSourceView *view,
                               GtkTooltip    *tooltip,
                               GSList        *marks)
{
	GtkWidget *vbox = NULL;

	for (; marks; marks = g_slist_next (marks))
	{
		const gchar *category;
		GtkSourceMark *mark;
		GtkSourceMarkAttributes *attrs;
		gchar *text;
		gboolean ismarkup = FALSE;
		GtkWidget *label;
		GtkWidget *hbox;
		const GdkPixbuf *pixbuf;
		gint size;

		mark = marks->data;
		category = gtk_source_mark_get_category (mark);

		attrs = gtk_source_view_get_mark_attributes (view,
		                                             category,
		                                             NULL);

		if (attrs == NULL)
		{
			continue;
		}

		text = gtk_source_mark_attributes_get_tooltip_markup (attrs,
		                                                      mark);

		if (text == NULL)
		{
			text = gtk_source_mark_attributes_get_tooltip_text (attrs,
			                                                    mark);
		}
		else
		{
			ismarkup = TRUE;
		}

		if (text == NULL)
		{
			continue;
		}

		if (vbox == NULL)
		{
			vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
			gtk_widget_show (vbox);
		}

		hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
		gtk_widget_show (hbox);
		gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

		label = gtk_label_new (NULL);

		if (ismarkup)
		{
			gtk_label_set_markup (GTK_LABEL (label), text);
		}
		else
		{
			gtk_label_set_text (GTK_LABEL (label), text);
		}

		gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
		gtk_widget_show (label);

		gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &size);
		pixbuf = gtk_source_mark_attributes_render_icon (attrs,
		                                                 GTK_WIDGET (view),
		                                                 size);

		if (pixbuf != NULL)
		{
			GtkWidget *image;
			PangoLayoutLine *line;
			PangoRectangle rect;
			GtkWidget *align;
			GdkPixbuf *copy;

			align = gtk_alignment_new (0, 0, 0, 0);
			gtk_widget_show (align);

			copy = gdk_pixbuf_copy (pixbuf);
			image = gtk_image_new_from_pixbuf (copy);
			g_object_unref (copy);

			gtk_misc_set_alignment (GTK_MISC (image), 0, 0);
			gtk_widget_show (image);

			/* Measure up to align exact */
			line = pango_layout_get_line (gtk_label_get_layout (GTK_LABEL (label)), 0);
			pango_layout_line_get_pixel_extents (line, NULL, &rect);

			gtk_alignment_set_padding (GTK_ALIGNMENT (align),
				                   (rect.height > size ? rect.height - size : size - rect.height) - 1,
				                   0, 0, 0);
			if (rect.height > size)
			{
				gtk_container_add (GTK_CONTAINER (align),
				                   image);

				image = align;
			}
			else if (size > rect.height)
			{
				gtk_container_add (GTK_CONTAINER (align),
				                   label);
				label = align;
			}
			else
			{
				gtk_widget_destroy (align);
			}

			gtk_box_pack_start (GTK_BOX (hbox),
			                    image,
			                    FALSE,
			                    FALSE,
			                    0);
		}

		gtk_box_pack_end (GTK_BOX (hbox),
		                  label,
		                  TRUE,
		                  TRUE,
		                  0);

		if (g_slist_length (marks) != 1)
		{
			GtkWidget *separator;

			separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);

			gtk_widget_show (separator);

			gtk_box_pack_start (GTK_BOX (vbox),
			                    separator,
			                    FALSE,
			                    FALSE,
			                    0);
		}

		g_free (text);
	}

	if (vbox == NULL)
	{
		return FALSE;
	}

	gtk_tooltip_set_custom (tooltip, vbox);

	return TRUE;
}