1 /* ide-buffer-change-monitor.c
2 *
3 * Copyright 2015-2019 Christian Hergert <christian@hergert.me>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-3.0-or-later
19 */
20
21 #define G_LOG_DOMAIN "ide-buffer-change-monitor"
22
23 #include "config.h"
24
25 #include <glib/gi18n.h>
26
27 #include "ide-buffer.h"
28 #include "ide-buffer-change-monitor.h"
29 #include "ide-buffer-private.h"
30
31 typedef struct
32 {
33 IdeBuffer *buffer;
34 } IdeBufferChangeMonitorPrivate;
35
36 G_DEFINE_TYPE_WITH_PRIVATE (IdeBufferChangeMonitor, ide_buffer_change_monitor, IDE_TYPE_OBJECT)
37
38 enum {
39 PROP_0,
40 PROP_BUFFER,
41 N_PROPS
42 };
43
44 enum {
45 CHANGED,
46 N_SIGNALS
47 };
48
49 static GParamSpec *properties [N_PROPS];
50 static guint signals [N_SIGNALS];
51
52 IdeBufferLineChange
ide_buffer_change_monitor_get_change(IdeBufferChangeMonitor * self,guint line)53 ide_buffer_change_monitor_get_change (IdeBufferChangeMonitor *self,
54 guint line)
55 {
56 g_return_val_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self), IDE_BUFFER_LINE_CHANGE_NONE);
57
58 if G_LIKELY (IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->get_change)
59 return IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->get_change (self, line);
60 else
61 return IDE_BUFFER_LINE_CHANGE_NONE;
62 }
63
64 static void
ide_buffer_change_monitor_set_buffer(IdeBufferChangeMonitor * self,IdeBuffer * buffer)65 ide_buffer_change_monitor_set_buffer (IdeBufferChangeMonitor *self,
66 IdeBuffer *buffer)
67 {
68 IdeBufferChangeMonitorPrivate *priv = ide_buffer_change_monitor_get_instance_private (self);
69
70 g_return_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self));
71 g_return_if_fail (IDE_IS_BUFFER (buffer));
72
73 priv->buffer = g_object_ref (buffer);
74
75 if (IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->load)
76 IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->load (self, buffer);
77 }
78
79 void
ide_buffer_change_monitor_emit_changed(IdeBufferChangeMonitor * self)80 ide_buffer_change_monitor_emit_changed (IdeBufferChangeMonitor *self)
81 {
82 IdeBufferChangeMonitorPrivate *priv = ide_buffer_change_monitor_get_instance_private (self);
83
84 g_return_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self));
85
86 g_signal_emit (self, signals [CHANGED], 0);
87
88 if (priv->buffer)
89 _ide_buffer_line_flags_changed (priv->buffer);
90 }
91
92 static void
ide_buffer_change_monitor_destroy(IdeObject * object)93 ide_buffer_change_monitor_destroy (IdeObject *object)
94 {
95 IdeBufferChangeMonitor *self = (IdeBufferChangeMonitor *)object;
96 IdeBufferChangeMonitorPrivate *priv = ide_buffer_change_monitor_get_instance_private (self);
97
98 g_assert (IDE_IS_MAIN_THREAD ());
99 g_assert (IDE_IS_BUFFER_CHANGE_MONITOR (self));
100
101 g_clear_object (&priv->buffer);
102
103 IDE_OBJECT_CLASS (ide_buffer_change_monitor_parent_class)->destroy (object);
104 }
105
106 static void
ide_buffer_change_monitor_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)107 ide_buffer_change_monitor_get_property (GObject *object,
108 guint prop_id,
109 GValue *value,
110 GParamSpec *pspec)
111 {
112 IdeBufferChangeMonitor *self = IDE_BUFFER_CHANGE_MONITOR (object);
113
114 switch (prop_id)
115 {
116 case PROP_BUFFER:
117 g_value_set_object (value, ide_buffer_change_monitor_get_buffer (self));
118 break;
119
120 default:
121 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122 }
123 }
124
125 static void
ide_buffer_change_monitor_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)126 ide_buffer_change_monitor_set_property (GObject *object,
127 guint prop_id,
128 const GValue *value,
129 GParamSpec *pspec)
130 {
131 IdeBufferChangeMonitor *self = IDE_BUFFER_CHANGE_MONITOR (object);
132
133 switch (prop_id)
134 {
135 case PROP_BUFFER:
136 ide_buffer_change_monitor_set_buffer (self, g_value_get_object (value));
137 break;
138
139 default:
140 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
141 }
142 }
143
144 static void
ide_buffer_change_monitor_class_init(IdeBufferChangeMonitorClass * klass)145 ide_buffer_change_monitor_class_init (IdeBufferChangeMonitorClass *klass)
146 {
147 GObjectClass *object_class = G_OBJECT_CLASS (klass);
148 IdeObjectClass *i_object_class = IDE_OBJECT_CLASS (klass);
149
150 object_class->get_property = ide_buffer_change_monitor_get_property;
151 object_class->set_property = ide_buffer_change_monitor_set_property;
152
153 i_object_class->destroy = ide_buffer_change_monitor_destroy;
154
155 properties [PROP_BUFFER] =
156 g_param_spec_object ("buffer",
157 "Buffer",
158 "The IdeBuffer to be monitored.",
159 IDE_TYPE_BUFFER,
160 (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
161
162 g_object_class_install_properties (object_class, N_PROPS, properties);
163
164 signals [CHANGED] = g_signal_new ("changed",
165 G_TYPE_FROM_CLASS (klass),
166 G_SIGNAL_RUN_LAST,
167 0,
168 NULL, NULL, NULL,
169 G_TYPE_NONE,
170 0);
171 }
172
173 static void
ide_buffer_change_monitor_init(IdeBufferChangeMonitor * self)174 ide_buffer_change_monitor_init (IdeBufferChangeMonitor *self)
175 {
176 }
177
178 void
ide_buffer_change_monitor_reload(IdeBufferChangeMonitor * self)179 ide_buffer_change_monitor_reload (IdeBufferChangeMonitor *self)
180 {
181 g_return_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self));
182
183 if (IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->reload)
184 IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->reload (self);
185 }
186
187 /**
188 * ide_buffer_change_monitor_foreach_change:
189 * @self: a #IdeBufferChangeMonitor
190 * @line_begin: the starting line
191 * @line_end: the end line
192 * @callback: (scope call): a callback
193 * @user_data: user data for @callback
194 *
195 * Calls @callback for every line between @line_begin and @line_end that have
196 * an addition, deletion, or change.
197 *
198 * Since: 3.32
199 */
200 void
ide_buffer_change_monitor_foreach_change(IdeBufferChangeMonitor * self,guint line_begin,guint line_end,IdeBufferChangeMonitorForeachFunc callback,gpointer user_data)201 ide_buffer_change_monitor_foreach_change (IdeBufferChangeMonitor *self,
202 guint line_begin,
203 guint line_end,
204 IdeBufferChangeMonitorForeachFunc callback,
205 gpointer user_data)
206 {
207 g_return_if_fail (IDE_IS_MAIN_THREAD ());
208 g_return_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self));
209 g_return_if_fail (callback != NULL);
210
211 if (IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->foreach_change)
212 IDE_BUFFER_CHANGE_MONITOR_GET_CLASS (self)->foreach_change (self, line_begin, line_end, callback, user_data);
213 }
214
215 /**
216 * ide_buffer_change_monitor_get_buffer:
217 * @self: a #IdeBufferChangeMonitor
218 *
219 * Gets the #IdeBufferChangeMonitor:buffer property.
220 *
221 * Returns: (transfer none): an #IdeBuffer
222 *
223 * Since: 3.32
224 */
225 IdeBuffer *
ide_buffer_change_monitor_get_buffer(IdeBufferChangeMonitor * self)226 ide_buffer_change_monitor_get_buffer (IdeBufferChangeMonitor *self)
227 {
228 IdeBufferChangeMonitorPrivate *priv = ide_buffer_change_monitor_get_instance_private (self);
229
230 g_return_val_if_fail (IDE_IS_BUFFER_CHANGE_MONITOR (self), NULL);
231
232 return priv->buffer;
233 }
234