1 /*
2 * textbox.c
3 *
4 *
5 * Author:
6 * Richard Hult <rhult@hem.passagen.se>
7 * Ricardo Markiewicz <rmarkie@fi.uba.ar>
8 * Andres de Barbara <adebarbara@fi.uba.ar>
9 * Marc Lorber <lorber.marc@wanadoo.fr>
10 *
11 * Web page: https://ahoi.io/project/oregano
12 *
13 * Copyright (C) 1999-2001 Richard Hult
14 * Copyright (C) 2003,2006 Ricardo Markiewicz
15 * Copyright (C) 2009-2012 Marc Lorber
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of the
20 * License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public
28 * License along with this program; if not, write to the
29 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
30 * Boston, MA 02110-1301, USA.
31 */
32
33 #include <math.h>
34 #include <goocanvas.h>
35
36 #include "textbox.h"
37 #include "clipboard.h"
38 #include "node-store.h"
39 #include "schematic-print-context.h"
40
41 #define TEXTBOX_DEFAULT_FONT "Arial 10"
42
43 // Private declarations
44
45 static void textbox_class_init (TextboxClass *klass);
46 static void textbox_init (Textbox *textbox);
47 static void textbox_copy (ItemData *dest, ItemData *src);
48 static ItemData *textbox_clone (ItemData *src);
49 static void textbox_rotate (ItemData *data, int angle, Coords *center);
50 static void textbox_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx);
51 static int textbox_register (ItemData *data);
52 static void textbox_unregister (ItemData *data);
53 static gboolean textbox_has_properties (ItemData *data);
54
55 static void textbox_flip (ItemData *data, IDFlip direction, Coords *center);
56
57 enum { TEXT_CHANGED, FONT_CHANGED, LAST_SIGNAL };
58
59 struct _TextboxPriv
60 {
61 char *text;
62 char *font;
63 };
64
65 G_DEFINE_TYPE (Textbox, textbox, TYPE_ITEM_DATA)
66
67 static guint textbox_signals[LAST_SIGNAL] = {0};
68
textbox_finalize(GObject * object)69 static void textbox_finalize (GObject *object)
70 {
71 Textbox *textbox = TEXTBOX (object);
72 TextboxPriv *priv = textbox->priv;
73
74 g_free (priv);
75
76 G_OBJECT_CLASS (textbox_parent_class)->finalize (object);
77 }
78
textbox_dispose(GObject * object)79 static void textbox_dispose (GObject *object)
80 {
81 G_OBJECT_CLASS (textbox_parent_class)->dispose (object);
82 }
83
textbox_class_init(TextboxClass * klass)84 static void textbox_class_init (TextboxClass *klass)
85 {
86 GObjectClass *object_class;
87 ItemDataClass *item_data_class;
88
89 textbox_parent_class = g_type_class_peek (TYPE_ITEM_DATA);
90 item_data_class = ITEM_DATA_CLASS (klass);
91 object_class = G_OBJECT_CLASS (klass);
92
93 textbox_signals[TEXT_CHANGED] =
94 g_signal_new ("text_changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL,
95 NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
96
97 textbox_signals[FONT_CHANGED] =
98 g_signal_new ("font_changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL,
99 NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
100
101 object_class->finalize = textbox_finalize;
102 object_class->dispose = textbox_dispose;
103
104 item_data_class->clone = textbox_clone;
105 item_data_class->copy = textbox_copy;
106 item_data_class->rotate = textbox_rotate;
107 item_data_class->flip = textbox_flip;
108 item_data_class->unreg = textbox_unregister;
109 item_data_class->reg = textbox_register;
110 item_data_class->has_properties = textbox_has_properties;
111 item_data_class->print = textbox_print;
112 }
113
textbox_init(Textbox * textbox)114 static void textbox_init (Textbox *textbox)
115 {
116 TextboxPriv *priv = g_new0 (TextboxPriv, 1);
117 textbox->priv = priv;
118 }
119
textbox_new(char * font)120 Textbox *textbox_new (char *font)
121 {
122 Textbox *textbox;
123
124 textbox = TEXTBOX (g_object_new (TYPE_TEXTBOX, NULL));
125
126 if (font == NULL)
127 textbox->priv->font = g_strdup (TEXTBOX_DEFAULT_FONT);
128 else
129 textbox->priv->font = g_strdup (font);
130
131 return textbox;
132 }
133
textbox_clone(ItemData * src)134 static ItemData *textbox_clone (ItemData *src)
135 {
136 Textbox *new_textbox;
137 ItemDataClass *id_class;
138
139 g_return_val_if_fail (src != NULL, NULL);
140 g_return_val_if_fail (IS_TEXTBOX (src), NULL);
141
142 id_class = ITEM_DATA_CLASS (G_OBJECT_GET_CLASS (src));
143 if (id_class->copy == NULL)
144 return NULL;
145
146 new_textbox = TEXTBOX (g_object_new (TYPE_TEXTBOX, NULL));
147 id_class->copy (ITEM_DATA (new_textbox), src);
148
149 return ITEM_DATA (new_textbox);
150 }
151
textbox_copy(ItemData * dest,ItemData * src)152 static void textbox_copy (ItemData *dest, ItemData *src)
153 {
154 Textbox *dest_textbox, *src_textbox;
155
156 g_return_if_fail (dest != NULL);
157 g_return_if_fail (IS_TEXTBOX (dest));
158 g_return_if_fail (src != NULL);
159 g_return_if_fail (IS_TEXTBOX (src));
160
161 if (ITEM_DATA_CLASS (textbox_parent_class)->copy != NULL)
162 ITEM_DATA_CLASS (textbox_parent_class)->copy (dest, src);
163
164 dest_textbox = TEXTBOX (dest);
165 src_textbox = TEXTBOX (src);
166
167 dest_textbox->priv->text = src_textbox->priv->text;
168 dest_textbox->priv->font = src_textbox->priv->font;
169 }
170
textbox_rotate(ItemData * data,int angle,Coords * center)171 static void textbox_rotate (ItemData *data, int angle, Coords *center)
172 {
173 cairo_matrix_t affine;
174 double x, y;
175 Textbox *textbox;
176 Coords b1, b2;
177 Coords textbox_center, delta;
178
179 g_return_if_fail (data != NULL);
180 g_return_if_fail (IS_TEXTBOX (data));
181
182 if (angle == 0)
183 return;
184
185 textbox = TEXTBOX (data);
186
187 if (center) {
188 item_data_get_absolute_bbox (ITEM_DATA (textbox), &b1, &b2);
189 textbox_center.x = b1.x + (b2.x - b1.x) / 2;
190 textbox_center.y = b1.y + (b2.y - b1.y) / 2;
191 }
192
193 cairo_matrix_init_rotate (&affine, (double)angle * M_PI / 180);
194
195 // Let the views (canvas items) know about the rotation.
196 g_signal_emit_by_name (G_OBJECT (textbox), "rotated", angle);
197
198 if (center) {
199 Coords textbox_pos;
200
201 item_data_get_pos (ITEM_DATA (textbox), &textbox_pos);
202
203 x = textbox_center.x - center->x;
204 y = textbox_center.y - center->y;
205 cairo_matrix_transform_point (&affine, &x, &y);
206
207 delta.x = x - (textbox_center.x - center->x);
208 delta.y = y - (textbox_center.y - center->y);
209
210 item_data_move (ITEM_DATA (textbox), &delta);
211 }
212 }
213
textbox_flip(ItemData * data,IDFlip direction,Coords * center)214 static void textbox_flip (ItemData *data, IDFlip direction, Coords *center)
215 {
216 cairo_matrix_t affine;
217 double x, y;
218 Textbox *textbox;
219 Coords b1, b2;
220 Coords textbox_center = {0.0, 0.0}, delta;
221
222 g_return_if_fail (data != NULL);
223 g_return_if_fail (IS_TEXTBOX (data));
224
225 textbox = TEXTBOX (data);
226
227 if (center) {
228 item_data_get_absolute_bbox (ITEM_DATA (textbox), &b1, &b2);
229 textbox_center.x = b1.x + (b2.x - b1.x) / 2;
230 textbox_center.y = b1.y + (b2.y - b1.y) / 2;
231 }
232
233 if (direction == ID_FLIP_HORIZ)
234 cairo_matrix_init_scale (&affine, -1, 1);
235 else
236 cairo_matrix_init_scale (&affine, 1, -1);
237
238 // Let the views (canvas items) know about the rotation.
239 g_signal_emit_by_name (G_OBJECT (textbox), "flipped", direction);
240
241 if (center) {
242 Coords textbox_pos;
243
244 item_data_get_pos (ITEM_DATA (textbox), &textbox_pos);
245
246 x = textbox_center.x - center->x;
247 y = textbox_center.y - center->y;
248 cairo_matrix_transform_point (&affine, &x, &y);
249
250 delta.x = x - (textbox_center.x - center->x);
251 delta.y = y - (textbox_center.y - center->y);
252
253 item_data_move (ITEM_DATA (textbox), &delta);
254 }
255 }
256
textbox_update_bbox(Textbox * textbox)257 void textbox_update_bbox (Textbox *textbox)
258 {
259 Coords b1, b2;
260 b1.x = 0.0;
261 b1.y = 0.0 - 5; // - font->ascent;
262 b2.x = 0.0 + 5; // + rbearing;
263 b2.y = 0.0 + 5; // + font->descent;
264
265 item_data_set_relative_bbox (ITEM_DATA (textbox), &b1, &b2);
266 }
267
textbox_has_properties(ItemData * data)268 static gboolean textbox_has_properties (ItemData *data) { return TRUE; }
269
textbox_set_text(Textbox * textbox,const char * text)270 void textbox_set_text (Textbox *textbox, const char *text)
271 {
272 g_return_if_fail (textbox != NULL);
273 g_return_if_fail (IS_TEXTBOX (textbox));
274
275 g_free (textbox->priv->text);
276 textbox->priv->text = g_strdup (text);
277
278 textbox_update_bbox (textbox);
279 g_signal_emit_by_name (G_OBJECT (textbox), "text_changed", text);
280 }
281
textbox_get_text(Textbox * textbox)282 char *textbox_get_text (Textbox *textbox)
283 {
284 g_return_val_if_fail (textbox != NULL, NULL);
285 g_return_val_if_fail (IS_TEXTBOX (textbox), NULL);
286
287 return textbox->priv->text;
288 }
289
textbox_set_font(Textbox * textbox,char * font)290 void textbox_set_font (Textbox *textbox, char *font)
291 {
292 g_return_if_fail (textbox != NULL);
293 g_return_if_fail (IS_TEXTBOX (textbox));
294
295 g_free (textbox->priv->font);
296 if (font == NULL)
297 textbox->priv->font = g_strdup (TEXTBOX_DEFAULT_FONT);
298 else
299 textbox->priv->font = g_strdup (font);
300
301 textbox_update_bbox (textbox);
302
303 g_signal_emit_by_name (G_OBJECT (textbox), "font_changed", textbox->priv->font);
304 }
305
textbox_get_font(Textbox * textbox)306 char *textbox_get_font (Textbox *textbox)
307 {
308 g_return_val_if_fail (textbox != NULL, NULL);
309 g_return_val_if_fail (IS_TEXTBOX (textbox), NULL);
310
311 return textbox->priv->font;
312 }
313
textbox_print(ItemData * data,cairo_t * cr,SchematicPrintContext * ctx)314 static void textbox_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx)
315 {
316 /* GnomeCanvasPoints *line;
317 double x0, y0;
318 ArtPoint dst, src;
319 double affine[6];
320 int i;
321 Textbox *textbox;
322 TextboxPriv *priv;
323 Coords pos;
324
325 g_return_if_fail (data != NULL);
326 g_return_if_fail (IS_TEXTBOX (data));
327
328 textbox = TEXTBOX (data);
329 priv = textbox->priv;
330
331 item_data_get_pos (ITEM_DATA (textbox), &pos);
332 src.x = pos.x;
333 src.y = pos.y;
334
335 art_affine_identity (affine);
336
337 gnome_print_setfont (opc->ctx,
338 gnome_font_face_get_font_default (opc->label_font, 6));
339 print_draw_text (opc->ctx, priv->text, &src);
340 */
341 }
342
textbox_unregister(ItemData * data)343 static void textbox_unregister (ItemData *data)
344 {
345 NodeStore *store;
346
347 g_return_if_fail (IS_TEXTBOX (data));
348
349 store = item_data_get_store (data);
350 node_store_remove_textbox (store, TEXTBOX (data));
351 }
352
textbox_register(ItemData * data)353 static int textbox_register (ItemData *data)
354 {
355 NodeStore *store;
356
357 g_return_val_if_fail (IS_TEXTBOX (data), 0);
358
359 store = item_data_get_store (data);
360 node_store_add_textbox (store, TEXTBOX (data));
361 return 0;
362 }
363