Commit bbb17707 authored by Christian Hergert's avatar Christian Hergert

xml-pack: remove use of weak pointers

We really don't want to be in the game of adding/removing weak pointers
when we can't reliably clear them (due to some design issues in GObject)
when second-degree (or more) objects are used.

So instead try to avoid using them altogether.

This might be related to #531
parent f5c06c38
Pipeline #16017 passed with stage
in 17 minutes and 45 seconds
......@@ -16,6 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#define G_LOG_DOMAIN "ide-xml-highlighter"
#include <dazzle.h>
#include <glib/gi18n.h>
......@@ -28,11 +32,8 @@
struct _IdeXmlHighlighter
{
IdeObject parent_instance;
DzlSignalGroup *signal_group;
GtkTextMark *iter_mark;
IdeHighlightEngine *engine;
GtkTextBuffer *buffer;
DzlSignalGroup *buffer_signals;
guint highlight_timeout;
guint has_tags : 1;
};
......@@ -48,18 +49,20 @@ static gboolean
ide_xml_highlighter_highlight_timeout_handler (gpointer data)
{
IdeXmlHighlighter *self = data;
GtkTextBuffer *buffer;
GtkTextMark *insert;
GtkTextTag *tag;
GtkTextIter iter;
GtkTextIter start;
GtkTextIter end;
g_assert (IDE_IS_XML_HIGHLIGHTER (self));
g_assert (self->buffer != NULL);
g_assert (self->iter_mark != NULL);
if (self->engine == NULL)
goto cleanup;
buffer = GTK_TEXT_BUFFER (ide_highlight_engine_get_buffer (self->engine));
insert = gtk_text_buffer_get_insert (buffer);
tag = ide_highlight_engine_get_style (self->engine, XML_TAG_MATCH_STYLE_NAME);
/*
......@@ -69,51 +72,40 @@ ide_xml_highlighter_highlight_timeout_handler (gpointer data)
*/
if (self->has_tags)
{
gtk_text_buffer_get_bounds (self->buffer, &start, &end);
gtk_text_buffer_remove_tag (self->buffer, tag, &start, &end);
gtk_text_buffer_get_bounds (buffer, &start, &end);
gtk_text_buffer_remove_tag (buffer, tag, &start, &end);
self->has_tags = FALSE;
}
gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, self->iter_mark);
if (ide_xml_in_element (&iter) && ide_xml_get_current_element (&iter,
&start,
&end))
if (ide_xml_in_element (&iter) && ide_xml_get_current_element (&iter, &start, &end))
{
IdeXmlElementTagType tag_type = ide_xml_get_element_tag_type (&start, &end);
GtkTextIter next_start;
GtkTextIter next_end;
IdeXmlElementTagType tag_type = ide_xml_get_element_tag_type (&start,
&end);
if ((tag_type == IDE_XML_ELEMENT_TAG_START &&
ide_xml_find_closing_element (&start,&end,
&next_start,&next_end)) ||
ide_xml_find_closing_element (&start, &end, &next_start, &next_end)) ||
(tag_type == IDE_XML_ELEMENT_TAG_END &&
ide_xml_find_opening_element (&start,&end,
&next_start,&next_end)) ||
ide_xml_find_opening_element (&start, &end, &next_start, &next_end)) ||
tag_type == IDE_XML_ELEMENT_TAG_START_END)
{
/*
* All iters point to the begining of < char and the
* beginning of > char.In our case we want to highlight everything that is
* between those two chars.This is the reason we move one char forward
* from the start iter
* All iters point to the begining of < char and the beginning of >
* char. In our case we want to highlight everything that is between
* those two chars.This is the reason we move one char forward from
* the start iter.
*/
gtk_text_iter_forward_char (&start);
gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (self->buffer),
tag,
&start,
&end);
gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
if (tag_type != IDE_XML_ELEMENT_TAG_START_END)
{
gtk_text_iter_forward_char (&next_start);
gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (self->buffer),
tag,
&next_start,
&next_end);
gtk_text_buffer_apply_tag (buffer, tag, &next_start, &next_end);
}
self->has_tags = TRUE;
......@@ -127,84 +119,53 @@ cleanup:
}
static void
ide_xml_highlighter_bind_buffer_cb (IdeXmlHighlighter *self,
IdeBuffer *buffer,
DzlSignalGroup *group)
ide_xml_highlighter_cursor_moved (IdeXmlHighlighter *self,
const GtkTextIter *iter,
IdeBuffer *buffer)
{
GtkTextIter begin;
g_assert (IDE_IS_XML_HIGHLIGHTER (self));
g_assert (iter != NULL);
g_assert (IDE_IS_BUFFER (buffer));
g_assert (DZL_IS_SIGNAL_GROUP (group));
dzl_set_weak_pointer (&self->buffer, GTK_TEXT_BUFFER (buffer));
gtk_text_buffer_get_start_iter (self->buffer, &begin);
self->iter_mark = gtk_text_buffer_create_mark (self->buffer, NULL, &begin, TRUE);
}
static void
ide_xml_highlighter_unbind_buffer_cb (IdeXmlHighlighter *self,
DzlSignalGroup *group)
{
g_assert (IDE_IS_XML_HIGHLIGHTER (self));
g_assert (DZL_IS_SIGNAL_GROUP (group));
g_assert (self->buffer != NULL);
if (self->highlight_timeout != 0)
{
g_source_remove (self->highlight_timeout);
self->highlight_timeout = 0;
}
gtk_text_buffer_delete_mark (self->buffer, self->iter_mark);
self->iter_mark = NULL;
dzl_clear_source (&self->highlight_timeout);
dzl_clear_weak_pointer (&self->buffer);
self->highlight_timeout =
gdk_threads_add_timeout_full (G_PRIORITY_LOW,
HIGHLIGH_TIMEOUT_MSEC,
ide_xml_highlighter_highlight_timeout_handler,
g_object_ref (self),
g_object_unref);
}
static void
ide_xml_highlighter_cursor_moved_cb (GtkTextBuffer *buffer,
GtkTextIter *iter,
IdeXmlHighlighter *self)
ide_xml_highlighter_dispose (GObject *object)
{
g_assert (IDE_IS_HIGHLIGHTER (self));
g_assert (GTK_IS_TEXT_BUFFER (buffer) && self->buffer == buffer);
IdeXmlHighlighter *self = (IdeXmlHighlighter *)object;
if (self->highlight_timeout != 0)
g_source_remove (self->highlight_timeout);
dzl_clear_source (&self->highlight_timeout);
g_clear_object (&self->buffer_signals);
gtk_text_buffer_move_mark (buffer, self->iter_mark, iter);
self->highlight_timeout = g_timeout_add (HIGHLIGH_TIMEOUT_MSEC,
ide_xml_highlighter_highlight_timeout_handler,
self);
G_OBJECT_CLASS (ide_xml_highlighter_parent_class)->dispose (object);
}
static void
ide_xml_highlighter_set_buffer (IdeXmlHighlighter *highlighter,
IdeBuffer *buffer)
ide_xml_highlighter_class_init (IdeXmlHighlighterClass *klass)
{
IdeXmlHighlighter *self = (IdeXmlHighlighter *)highlighter;
g_assert (IDE_IS_HIGHLIGHTER (self));
g_assert (!buffer || IDE_IS_BUFFER (buffer));
GObjectClass *object_class = G_OBJECT_CLASS (klass);
dzl_signal_group_set_target (self->signal_group, buffer);
object_class->dispose = ide_xml_highlighter_dispose;
}
static void
ide_xml_highlighter_on_buffer_set (IdeXmlHighlighter *self,
GParamSpec *pspec,
IdeHighlightEngine *engine)
ide_xml_highlighter_init (IdeXmlHighlighter *self)
{
IdeBuffer *buffer;
self->buffer_signals = dzl_signal_group_new (IDE_TYPE_BUFFER);
g_assert (IDE_IS_XML_HIGHLIGHTER (self));
g_assert (IDE_IS_HIGHLIGHT_ENGINE (engine));
buffer = ide_highlight_engine_get_buffer (engine);
ide_xml_highlighter_set_buffer (self, buffer);
dzl_signal_group_connect_object (self->buffer_signals,
"cursor-moved",
G_CALLBACK (ide_xml_highlighter_cursor_moved),
self,
G_CONNECT_SWAPPED);
}
static void
......@@ -214,77 +175,45 @@ ide_xml_highlighter_real_set_engine (IdeHighlighter *highlighter,
IdeXmlHighlighter *self = (IdeXmlHighlighter *)highlighter;
IdeBuffer *buffer = NULL;
g_return_if_fail (IDE_IS_XML_HIGHLIGHTER (self));
g_return_if_fail (IDE_IS_HIGHLIGHT_ENGINE (engine));
if (dzl_set_weak_pointer (&self->engine, engine))
{
buffer = ide_highlight_engine_get_buffer (engine);
/*
* TODO: technically we should connect/disconnect when the
* highlighter changes. but in practice, it is set only
* once.
*/
g_signal_connect_object (engine,
"notify::buffer",
G_CALLBACK (ide_xml_highlighter_on_buffer_set),
self,
G_CONNECT_SWAPPED);
}
ide_xml_highlighter_set_buffer (self, buffer);
}
g_assert (IDE_IS_XML_HIGHLIGHTER (self));
g_assert (!engine || IDE_IS_HIGHLIGHT_ENGINE (engine));
static void
ide_xml_highlighter_dispose (GObject *object)
{
IdeXmlHighlighter *self = (IdeXmlHighlighter *)object;
self->engine = engine;
if (self->highlight_timeout != 0)
if (engine != NULL)
{
g_source_remove (self->highlight_timeout);
self->highlight_timeout = 0;
}
dzl_clear_weak_pointer (&self->engine);
g_clear_object (&self->signal_group);
GtkTextIter insert;
G_OBJECT_CLASS (ide_xml_highlighter_parent_class)->dispose (object);
}
static void
ide_xml_highlighter_class_init (IdeXmlHighlighterClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
buffer = ide_highlight_engine_get_buffer (engine);
ide_buffer_get_selection_bounds (buffer, &insert, NULL);
ide_xml_highlighter_cursor_moved (self, &insert, buffer);
}
object_class->dispose = ide_xml_highlighter_dispose;
dzl_signal_group_set_target (self->buffer_signals, buffer);
}
static void
ide_xml_highlighter_init (IdeXmlHighlighter *self)
ide_xml_highlighter_real_update (IdeHighlighter *highlighter,
IdeHighlightCallback callback,
const GtkTextIter *range_begin,
const GtkTextIter *range_end,
GtkTextIter *location)
{
self->signal_group = dzl_signal_group_new (IDE_TYPE_BUFFER);
dzl_signal_group_connect_object (self->signal_group,
"cursor-moved",
G_CALLBACK (ide_xml_highlighter_cursor_moved_cb),
self,
0);
g_signal_connect_object (self->signal_group,
"bind",
G_CALLBACK (ide_xml_highlighter_bind_buffer_cb),
self,
G_CONNECT_SWAPPED);
g_signal_connect_object (self->signal_group,
"unbind",
G_CALLBACK (ide_xml_highlighter_unbind_buffer_cb),
self,
G_CONNECT_SWAPPED);
g_assert (IDE_IS_XML_HIGHLIGHTER (highlighter));
g_assert (range_begin != NULL);
g_assert (range_end != NULL);
g_assert (location != NULL);
/* We don't do any immediate processing. So let the engine thing
* we are done immediately. Instead, we'll introduce a delay to
* update the matching element.
*/
*location = *range_end;
}
static void
highlighter_iface_init (IdeHighlighterInterface *iface)
{
iface->set_engine = ide_xml_highlighter_real_set_engine;
iface->update = ide_xml_highlighter_real_update;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment