1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * GimpTextEditor
5 * Copyright (C) 2002-2003, 2008 Sven Neumann <sven@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25
26 #include "libgimpwidgets/gimpwidgets.h"
27
28 #include "widgets-types.h"
29
30 #include "core/gimp.h"
31 #include "core/gimpdatafactory.h"
32 #include "core/gimpmarshal.h"
33
34 #include "text/gimptext.h"
35
36 #include "gimphelp-ids.h"
37 #include "gimpmenufactory.h"
38 #include "gimptextbuffer.h"
39 #include "gimptexteditor.h"
40 #include "gimptextstyleeditor.h"
41 #include "gimpuimanager.h"
42
43 #include "gimp-intl.h"
44
45
46 enum
47 {
48 TEXT_CHANGED,
49 DIR_CHANGED,
50 LAST_SIGNAL
51 };
52
53
54 static void gimp_text_editor_finalize (GObject *object);
55
56 static void gimp_text_editor_text_changed (GtkTextBuffer *buffer,
57 GimpTextEditor *editor);
58 static void gimp_text_editor_font_toggled (GtkToggleButton *button,
59 GimpTextEditor *editor);
60
61
62 G_DEFINE_TYPE (GimpTextEditor, gimp_text_editor, GIMP_TYPE_DIALOG)
63
64 #define parent_class gimp_text_editor_parent_class
65
66 static guint text_editor_signals[LAST_SIGNAL] = { 0 };
67
68
69 static void
gimp_text_editor_class_init(GimpTextEditorClass * klass)70 gimp_text_editor_class_init (GimpTextEditorClass *klass)
71 {
72 GObjectClass *object_class = G_OBJECT_CLASS (klass);
73
74 object_class->finalize = gimp_text_editor_finalize;
75
76 klass->text_changed = NULL;
77 klass->dir_changed = NULL;
78
79 text_editor_signals[TEXT_CHANGED] =
80 g_signal_new ("text-changed",
81 G_TYPE_FROM_CLASS (klass),
82 G_SIGNAL_RUN_FIRST,
83 G_STRUCT_OFFSET (GimpTextEditorClass, text_changed),
84 NULL, NULL,
85 gimp_marshal_VOID__VOID,
86 G_TYPE_NONE, 0);
87
88 text_editor_signals[DIR_CHANGED] =
89 g_signal_new ("dir-changed",
90 G_TYPE_FROM_CLASS (klass),
91 G_SIGNAL_RUN_FIRST,
92 G_STRUCT_OFFSET (GimpTextEditorClass, dir_changed),
93 NULL, NULL,
94 gimp_marshal_VOID__VOID,
95 G_TYPE_NONE, 0);
96 }
97
98 static void
gimp_text_editor_init(GimpTextEditor * editor)99 gimp_text_editor_init (GimpTextEditor *editor)
100 {
101 editor->view = NULL;
102 editor->file_dialog = NULL;
103 editor->ui_manager = NULL;
104
105 switch (gtk_widget_get_default_direction ())
106 {
107 case GTK_TEXT_DIR_NONE:
108 case GTK_TEXT_DIR_LTR:
109 editor->base_dir = GIMP_TEXT_DIRECTION_LTR;
110 break;
111 case GTK_TEXT_DIR_RTL:
112 editor->base_dir = GIMP_TEXT_DIRECTION_RTL;
113 break;
114 }
115 }
116
117 static void
gimp_text_editor_finalize(GObject * object)118 gimp_text_editor_finalize (GObject *object)
119 {
120 GimpTextEditor *editor = GIMP_TEXT_EDITOR (object);
121
122 g_clear_pointer (&editor->font_name, g_free);
123 g_clear_object (&editor->ui_manager);
124
125 G_OBJECT_CLASS (parent_class)->finalize (object);
126 }
127
128
129 /* public functions */
130
131 GtkWidget *
gimp_text_editor_new(const gchar * title,GtkWindow * parent,Gimp * gimp,GimpMenuFactory * menu_factory,GimpText * text,GimpTextBuffer * text_buffer,gdouble xres,gdouble yres)132 gimp_text_editor_new (const gchar *title,
133 GtkWindow *parent,
134 Gimp *gimp,
135 GimpMenuFactory *menu_factory,
136 GimpText *text,
137 GimpTextBuffer *text_buffer,
138 gdouble xres,
139 gdouble yres)
140 {
141 GimpTextEditor *editor;
142 GtkWidget *content_area;
143 GtkWidget *toolbar;
144 GtkWidget *style_editor;
145 GtkWidget *scrolled_window;
146
147 g_return_val_if_fail (title != NULL, NULL);
148 g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
149 g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
150 g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
151 g_return_val_if_fail (GIMP_IS_TEXT (text), NULL);
152 g_return_val_if_fail (GIMP_IS_TEXT_BUFFER (text_buffer), NULL);
153
154 editor = g_object_new (GIMP_TYPE_TEXT_EDITOR,
155 "title", title,
156 "role", "gimp-text-editor",
157 "transient-for", parent,
158 "help-func", gimp_standard_help_func,
159 "help-id", GIMP_HELP_TEXT_EDITOR_DIALOG,
160 NULL);
161
162 gtk_dialog_add_button (GTK_DIALOG (editor),
163 _("_Close"), GTK_RESPONSE_CLOSE);
164
165 g_signal_connect (editor, "response",
166 G_CALLBACK (gtk_widget_destroy),
167 NULL);
168
169 g_signal_connect_object (text_buffer, "changed",
170 G_CALLBACK (gimp_text_editor_text_changed),
171 editor, 0);
172
173 editor->ui_manager = gimp_menu_factory_manager_new (menu_factory,
174 "<TextEditor>",
175 editor, FALSE);
176
177 content_area = gtk_dialog_get_content_area (GTK_DIALOG (editor));
178
179 toolbar = gimp_ui_manager_get_widget (editor->ui_manager,
180 "/text-editor-toolbar");
181
182 if (toolbar)
183 {
184 gtk_box_pack_start (GTK_BOX (content_area), toolbar, FALSE, FALSE, 0);
185 gtk_widget_show (toolbar);
186 }
187
188 style_editor = gimp_text_style_editor_new (gimp, text, text_buffer,
189 gimp_data_factory_get_container (gimp->font_factory),
190 xres, yres);
191 gtk_box_pack_start (GTK_BOX (content_area), style_editor, FALSE, FALSE, 0);
192 gtk_widget_show (style_editor);
193
194 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
195 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
196 GTK_POLICY_AUTOMATIC,
197 GTK_POLICY_AUTOMATIC);
198 gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 2);
199 gtk_box_pack_start (GTK_BOX (content_area), scrolled_window, TRUE, TRUE, 0);
200 gtk_widget_show (scrolled_window);
201
202 editor->view = gtk_text_view_new_with_buffer (GTK_TEXT_BUFFER (text_buffer));
203 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (editor->view),
204 GTK_WRAP_WORD_CHAR);
205 gtk_container_add (GTK_CONTAINER (scrolled_window), editor->view);
206 gtk_widget_show (editor->view);
207
208 switch (editor->base_dir)
209 {
210 case GIMP_TEXT_DIRECTION_LTR:
211 case GIMP_TEXT_DIRECTION_TTB_RTL:
212 case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT:
213 case GIMP_TEXT_DIRECTION_TTB_LTR:
214 case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT:
215 gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_LTR);
216 break;
217 case GIMP_TEXT_DIRECTION_RTL:
218 gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_RTL);
219 break;
220 }
221
222 gtk_widget_set_size_request (editor->view, 200, 64);
223
224 editor->font_toggle =
225 gtk_check_button_new_with_mnemonic (_("_Use selected font"));
226 gtk_box_pack_start (GTK_BOX (content_area), editor->font_toggle,
227 FALSE, FALSE, 0);
228 gtk_widget_show (editor->font_toggle);
229
230 g_signal_connect (editor->font_toggle, "toggled",
231 G_CALLBACK (gimp_text_editor_font_toggled),
232 editor);
233
234 gtk_widget_grab_focus (editor->view);
235
236 gimp_ui_manager_update (editor->ui_manager, editor);
237
238 return GTK_WIDGET (editor);
239 }
240
241 void
gimp_text_editor_set_text(GimpTextEditor * editor,const gchar * text,gint len)242 gimp_text_editor_set_text (GimpTextEditor *editor,
243 const gchar *text,
244 gint len)
245 {
246 GtkTextBuffer *buffer;
247
248 g_return_if_fail (GIMP_IS_TEXT_EDITOR (editor));
249 g_return_if_fail (text != NULL || len == 0);
250
251 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
252
253 if (text)
254 gtk_text_buffer_set_text (buffer, text, len);
255 else
256 gtk_text_buffer_set_text (buffer, "", 0);
257 }
258
259 gchar *
gimp_text_editor_get_text(GimpTextEditor * editor)260 gimp_text_editor_get_text (GimpTextEditor *editor)
261 {
262 GtkTextBuffer *buffer;
263
264 g_return_val_if_fail (GIMP_IS_TEXT_EDITOR (editor), NULL);
265
266 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->view));
267
268 return gimp_text_buffer_get_text (GIMP_TEXT_BUFFER (buffer));
269 }
270
271 void
gimp_text_editor_set_direction(GimpTextEditor * editor,GimpTextDirection base_dir)272 gimp_text_editor_set_direction (GimpTextEditor *editor,
273 GimpTextDirection base_dir)
274 {
275 g_return_if_fail (GIMP_IS_TEXT_EDITOR (editor));
276
277 if (editor->base_dir == base_dir)
278 return;
279
280 editor->base_dir = base_dir;
281
282 if (editor->view)
283 {
284 switch (editor->base_dir)
285 {
286 case GIMP_TEXT_DIRECTION_LTR:
287 case GIMP_TEXT_DIRECTION_TTB_RTL:
288 case GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT:
289 case GIMP_TEXT_DIRECTION_TTB_LTR:
290 case GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT:
291 gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_LTR);
292 break;
293 case GIMP_TEXT_DIRECTION_RTL:
294 gtk_widget_set_direction (editor->view, GTK_TEXT_DIR_RTL);
295 break;
296 }
297 }
298
299 gimp_ui_manager_update (editor->ui_manager, editor);
300
301 g_signal_emit (editor, text_editor_signals[DIR_CHANGED], 0);
302 }
303
304 GimpTextDirection
gimp_text_editor_get_direction(GimpTextEditor * editor)305 gimp_text_editor_get_direction (GimpTextEditor *editor)
306 {
307 g_return_val_if_fail (GIMP_IS_TEXT_EDITOR (editor), GIMP_TEXT_DIRECTION_LTR);
308
309 return editor->base_dir;
310 }
311
312 void
gimp_text_editor_set_font_name(GimpTextEditor * editor,const gchar * font_name)313 gimp_text_editor_set_font_name (GimpTextEditor *editor,
314 const gchar *font_name)
315 {
316 g_return_if_fail (GIMP_IS_TEXT_EDITOR (editor));
317
318 if (editor->font_name)
319 g_free (editor->font_name);
320
321 editor->font_name = g_strdup (font_name);
322
323 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (editor->font_toggle)))
324 {
325 PangoFontDescription *font_desc = NULL;
326
327 if (font_name)
328 font_desc = pango_font_description_from_string (font_name);
329
330 gtk_widget_modify_font (editor->view, font_desc);
331
332 if (font_desc)
333 pango_font_description_free (font_desc);
334 }
335 }
336
337 const gchar *
gimp_text_editor_get_font_name(GimpTextEditor * editor)338 gimp_text_editor_get_font_name (GimpTextEditor *editor)
339 {
340 g_return_val_if_fail (GIMP_IS_TEXT_EDITOR (editor), NULL);
341
342 return editor->font_name;
343 }
344
345
346 /* private functions */
347
348 static void
gimp_text_editor_text_changed(GtkTextBuffer * buffer,GimpTextEditor * editor)349 gimp_text_editor_text_changed (GtkTextBuffer *buffer,
350 GimpTextEditor *editor)
351 {
352 g_signal_emit (editor, text_editor_signals[TEXT_CHANGED], 0);
353 }
354
355 static void
gimp_text_editor_font_toggled(GtkToggleButton * button,GimpTextEditor * editor)356 gimp_text_editor_font_toggled (GtkToggleButton *button,
357 GimpTextEditor *editor)
358 {
359 PangoFontDescription *font_desc = NULL;
360
361 if (gtk_toggle_button_get_active (button) && editor->font_name)
362 font_desc = pango_font_description_from_string (editor->font_name);
363
364 gtk_widget_modify_font (editor->view, font_desc);
365
366 if (font_desc)
367 pango_font_description_free (font_desc);
368 }
369