doc: update copyright line for 2021
[adg.git] / src / adg / adg-textual.c
blob46e414362e81b74bc6ea8dd86e59682f24cecaa1
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2021 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-textual
23 * @Section_Id:AdgTextual
24 * @title: AdgTextual
25 * @short_description: An interface for entities that embeds text
27 * The #AdgTextual interface should be implemented by entities that
28 * can be expressed by text. #AdgToyText is a typical case but also
29 * more complex entities could implement it.
31 * Since: 1.0
32 **/
34 /**
35 * AdgTextual:
37 * Dummy type of the #AdgTextualIface interface.
39 * Since: 1.0
40 **/
42 /**
43 * AdgTextualIface:
44 * @set_font_dress: abstract virtual method to change the font dress.
45 * @get_font_dress: abstract virtual method to get the active font dress.
46 * @set_text: abstract virtual method to set a new text.
47 * @dup_text: abstract virtual method that returns a duplicate of
48 * the actual text.
49 * @text_changed: default signal handler for #AdgTextual::text-changed.
51 * The virtual methods @set_text and @dup_text must be implemented
52 * by all the types which implement this interface.
54 * Since: 1.0
55 **/
58 #include "adg-internal.h"
59 #include "adg-dress.h"
60 #include "adg-param-dress.h"
62 #include "adg-textual.h"
65 enum {
66 TEXT_CHANGED,
67 LAST_SIGNAL
71 static void _adg_iface_base (AdgTextualIface *iface);
72 static gchar * _adg_dup_text (AdgTextual *textual,
73 AdgTextualIface *iface);
74 static guint _adg_signals[LAST_SIGNAL] = { 0 };
77 GType
78 adg_textual_get_type(void)
80 static GType textual_type = 0;
82 if (G_UNLIKELY(textual_type == 0)) {
83 const GTypeInfo textual_info = {
84 sizeof(AdgTextualIface),
85 (GBaseInitFunc) _adg_iface_base,
86 (GBaseFinalizeFunc) NULL,
87 (GClassInitFunc) NULL,
88 (GClassFinalizeFunc) NULL,
90 textual_type = g_type_register_static(G_TYPE_INTERFACE, "AdgTextual",
91 &textual_info, 0);
92 g_type_interface_add_prerequisite(ADG_TYPE_TEXTUAL, G_TYPE_OBJECT);
95 return textual_type;
98 static void
99 _adg_iface_base(AdgTextualIface *iface)
101 static gboolean initialized = FALSE;
102 GParamSpec *param;
104 if (G_LIKELY(initialized))
105 return;
107 initialized = TRUE;
109 param = g_param_spec_string("text",
110 P_("Text"),
111 P_("The text associated to this entity"),
112 NULL,
113 G_PARAM_READWRITE);
114 g_object_interface_install_property(iface, param);
116 param = adg_param_spec_dress("font-dress",
117 P_("Font Dress"),
118 P_("The font dress to use for rendering this text"),
119 ADG_DRESS_FONT_TEXT,
120 G_PARAM_READWRITE);
121 g_object_interface_install_property(iface, param);
124 * AdgTextual::text-changed:
125 * @textual: an entity that implements #AdgTextual
126 * @old_text: the old text
128 * Emitted whenever the text of @textual has been changed.
130 * Since: 1.0
132 _adg_signals[TEXT_CHANGED] =
133 g_signal_new("text-changed",
134 G_OBJECT_CLASS_TYPE(iface),
135 G_SIGNAL_RUN_LAST,
136 G_STRUCT_OFFSET(AdgTextualIface, text_changed),
137 NULL, NULL,
138 g_cclosure_marshal_VOID__POINTER,
139 G_TYPE_NONE, 1, G_TYPE_POINTER);
144 * adg_textual_set_font_dress:
145 * @textual: an object that implements #AdgTextual
146 * @dress: the new dress
148 * Sets the font dress of @textual to @dress.
150 * Since: 1.0
152 void
153 adg_textual_set_font_dress(AdgTextual *textual, AdgDress dress)
155 AdgTextualIface *iface;
157 g_return_if_fail(ADG_IS_TEXTUAL(textual));
159 /* The set_font_dress() method must be defined */
160 iface = ADG_TEXTUAL_GET_IFACE(textual);
161 if (iface->set_font_dress == NULL) {
162 g_warning(_("%s: 'set_font_dress' method not implemented for type '%s'"),
163 G_STRLOC, g_type_name(G_OBJECT_TYPE(textual)));
164 return;
167 iface->set_font_dress(textual, dress);
171 * adg_textual_get_font_dress:
172 * @textual: an object that implements #AdgTextual
174 * Gets the current font dress of @textual, eventually resolved to
175 * an #AdgFontStyle before the rendering.
177 * Returns: (transfer none): the current font dress of @textual.
179 * Since: 1.0
181 AdgDress
182 adg_textual_get_font_dress(AdgTextual *textual)
184 AdgTextualIface *iface;
186 g_return_val_if_fail(ADG_IS_TEXTUAL(textual), ADG_DRESS_UNDEFINED);
188 /* The get_font_dress() method must be defined */
189 iface = ADG_TEXTUAL_GET_IFACE(textual);
190 if (iface->get_font_dress == NULL) {
191 g_warning(_("%s: 'get_font_dress' method not implemented for type '%s'"),
192 G_STRLOC, g_type_name(G_OBJECT_TYPE(textual)));
193 return ADG_DRESS_UNDEFINED;
196 return iface->get_font_dress(textual);
200 * adg_textual_set_text:
201 * @textual: an object that implements #AdgTextual
202 * @text: the new text to be set
204 * Sets a new text on @textual. If @text is the same as the old text
205 * no actions are performed, otherwise the <function>set_text</function>
206 * virtual method is called and the #AdgTextual::text-changed signal
207 * is emitted.
209 * Since: 1.0
211 void
212 adg_textual_set_text(AdgTextual *textual, const gchar *text)
214 AdgTextualIface *iface;
215 gchar *old_text;
217 g_return_if_fail(ADG_IS_TEXTUAL(textual));
219 /* The set_text() method must be defined */
220 iface = ADG_TEXTUAL_GET_IFACE(textual);
221 if (iface->set_text == NULL) {
222 g_warning(_("%s: 'set_text' method not implemented for type '%s'"),
223 G_STRLOC, g_type_name(G_OBJECT_TYPE(textual)));
224 return;
227 old_text = _adg_dup_text(textual, iface);
228 if (g_strcmp0(text, old_text) != 0) {
229 iface->set_text(textual, text);
230 g_signal_emit(textual, _adg_signals[TEXT_CHANGED], 0, old_text);
233 g_free(old_text);
237 * adg_textual_dup_text:
238 * @textual: an object that implements #AdgTextual
240 * Gets a duplicate of the current text bound to @textual.
242 * Returns: the current text of @textual: free with g_free() when finished
244 * Since: 1.0
246 gchar *
247 adg_textual_dup_text(AdgTextual *textual)
249 g_return_val_if_fail(ADG_IS_TEXTUAL(textual), NULL);
251 return _adg_dup_text(textual, ADG_TEXTUAL_GET_IFACE(textual));
255 * adg_textual_text_changed:
256 * @textual: an object that implements #AdgTextual
257 * @old_text: the old text bound to @textual
259 * Emits the #AdgTextual::text-changed signal on @textual.
261 * <note><para>
262 * This function is only useful when creating a new class that implements
263 * the #AdgTextual interface.
264 * </para></note>
266 * Since: 1.0
268 void
269 adg_textual_text_changed(AdgTextual *textual, const gchar *old_text)
271 g_return_if_fail(ADG_IS_TEXTUAL(textual));
273 g_signal_emit(textual, _adg_signals[TEXT_CHANGED], 0, old_text);
277 static gchar *
278 _adg_dup_text(AdgTextual *textual, AdgTextualIface *iface)
280 if (iface->dup_text == NULL) {
281 g_warning(_("%s: 'dup_text' method not implemented for type '%s'"),
282 G_STRLOC, g_type_name(G_OBJECT_TYPE(textual)));
283 return NULL;
286 return iface->dup_text(textual);