Bump gEDA version
[geda-gaf.git] / gschem / src / x_newtext.c
blob81ef379fc88cb3277e0344b75c3e36c3cafeea90
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 2013 Ales Hvezda
4 * Copyright (C) 2013-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 /*!
21 * \file x_newtext.c
23 * \brief A dialog box for adding new text to a schematic.
26 #include <config.h>
28 #include <stdio.h>
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
36 #include "gschem.h"
37 #include <gdk/gdkkeysyms.h>
41 #define TYPE_NEWTEXT (newtext_get_type())
42 #define NEWTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NEWTEXT, NewText))
43 #define NEWTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NEWTEXT, NewTextClass))
44 #define IS_NEWTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NEWTEXT))
46 typedef struct _NewTextClass NewTextClass;
47 typedef struct _NewText NewText;
49 struct _NewTextClass {
50 GschemDialogClass parent_class;
53 struct _NewText {
54 GschemDialog parent;
56 GtkWidget *aligncb;
57 GtkWidget *colorcb;
58 GtkWidget *rotatecb;
59 GtkWidget *textsizecb;
60 GtkWidget *text_view;
65 /*! \brief Handles the user response when apply is selected
67 * \par Function Description
68 * This function applies the text from the text entry dialog.
70 * \param [in] dialog The new text dialog
72 static void
73 dialog_response_apply (NewText *dialog)
75 int align = LOWER_LEFT;
76 int color = TEXT_COLOR;
77 int rotate = 0;
78 int size = 12;
79 gchar *string = NULL;
80 gchar *tmp = NULL;
81 GtkTextBuffer *textbuffer;
82 GtkTextIter start, end;
83 int value;
85 textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(dialog->text_view));
86 gtk_text_buffer_get_bounds (textbuffer, &start, &end);
87 string = gtk_text_iter_get_text (&start, &end);
89 if (string[0] == '\0' )
90 return;
92 switch(dialog->parent.w_current->text_caps) {
93 case(LOWER):
94 tmp = g_utf8_strdown (string, -1);
95 break;
97 case(UPPER):
98 tmp = g_utf8_strup (string, -1);
99 break;
101 case(BOTH):
102 default:
103 /* do nothing */
104 break;
107 value = x_colorcb_get_index (dialog->colorcb);
108 if (value >= 0) {
109 color = value;
112 value = gschem_alignment_combo_get_align (dialog->aligncb);
113 if (value >= 0) {
114 align = value;
117 value = gschem_integer_combo_box_get_value (dialog->textsizecb);
118 if (value > 0) {
119 size = value;
122 value = gschem_rotation_combo_get_angle (dialog->rotatecb);
123 if (value >= 0) {
124 rotate = value;
127 /* select the text, so you can continue immediatly writing the next text */
128 select_all_text_in_textview(GTK_TEXT_VIEW(dialog->text_view));
129 gtk_widget_grab_focus(dialog->text_view);
131 o_text_prepare_place (dialog->parent.w_current,
132 tmp == NULL ? string : tmp,
133 color,
134 align,
135 rotate,
136 size);
138 //gschem_toplevel_page_content_changed (dialog->parent.w_current,
139 // dialog->parent.w_current->toplevel->page_current);
141 g_free (string);
142 g_free (tmp);
147 /*! \brief Handles the user response when cancel is selected
151 * \param [in,out] dialog The new text dialog
153 static void dialog_response_cancel(NewText *dialog)
155 i_cancel(dialog->parent.w_current);
156 gtk_widget_destroy(dialog->parent.w_current->tiwindow);
157 dialog->parent.w_current->tiwindow=NULL;
162 /*! \brief Handles user responses from the new text dialog box
164 * \par Function Description
165 * Callback function for the text entry dialog.
167 * \param [in,out] widget The new text dialog
168 * \param [na] unused Unused parameter
170 static void text_input_dialog_response(NewText *dialog, gint response, gpointer unused)
172 switch(response) {
173 case GTK_RESPONSE_APPLY:
174 dialog_response_apply(dialog);
175 break;
176 case GTK_RESPONSE_CLOSE:
177 case GTK_RESPONSE_DELETE_EVENT:
178 dialog_response_cancel(dialog);
179 break;
180 default:
181 printf("text_edit_dialog_response(): strange signal %d\n", response);
186 /*! \brief Initialize NewText class
188 * \par Function Description
190 * GType class initialiser for Multiattrib. We override our parent
191 * virtual class methods as needed and register our GObject properties.
193 * \param [in] klass
195 static void newtext_class_init(NewTextClass *klass)
201 /*! \brief Initialize NewText instance
203 * \param [in,out] dialog The new text dialog
205 static void newtext_init(NewText *dialog)
207 GtkWidget *alignment;
208 GtkWidget *vbox;
209 GtkWidget *label = NULL;
210 GtkWidget *viewport1 = NULL;
211 GtkWidget *scrolled_window = NULL;
212 PangoTabArray *tab_array;
213 int real_tab_width;
214 GtkWidget *table;
216 gtk_dialog_add_button (GTK_DIALOG (dialog),
217 GTK_STOCK_CLOSE,
218 GTK_RESPONSE_CLOSE);
220 gtk_dialog_add_button (GTK_DIALOG (dialog),
221 GTK_STOCK_APPLY,
222 GTK_RESPONSE_APPLY);
224 /* Set the alternative button order (ok, cancel, help) for other systems */
225 gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),
226 GTK_RESPONSE_ACCEPT,
227 GTK_RESPONSE_REJECT,
228 -1);
230 gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_NONE);
232 g_signal_connect (G_OBJECT (dialog), "response",
233 G_CALLBACK (text_input_dialog_response),
234 NULL);
236 gtk_dialog_set_default_response(GTK_DIALOG(dialog),
237 GTK_RESPONSE_ACCEPT);
239 vbox = GTK_DIALOG(dialog)->vbox;
240 gtk_box_set_spacing(GTK_BOX(vbox),DIALOG_V_SPACING);
242 table = gtk_table_new(4, 2, FALSE);
243 gtk_table_set_row_spacings(GTK_TABLE(table), DIALOG_V_SPACING);
244 gtk_table_set_col_spacings(GTK_TABLE(table), DIALOG_H_SPACING);
246 label = gtk_label_new(_("<b>Text Properties</b>"));
247 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
248 gtk_misc_set_alignment(GTK_MISC(label),0,0);
249 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
251 alignment = gtk_alignment_new(0,0,1,1);
252 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0,
253 DIALOG_INDENTATION, 0);
254 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
256 gtk_container_add(GTK_CONTAINER(alignment), table);
258 label = gtk_label_new (_("<b>Text Content</b>"));
259 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
260 gtk_misc_set_alignment(GTK_MISC(label),0,0);
261 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
264 label = gtk_label_new (_("Color:"));
265 gtk_misc_set_alignment(GTK_MISC(label),0,0);
266 gtk_table_attach(GTK_TABLE(table), label, 0,1,0,1, GTK_FILL,0,0,0);
268 dialog->colorcb = x_colorcb_new ();
269 x_colorcb_set_index(dialog->colorcb, TEXT_COLOR);
270 gtk_table_attach_defaults(GTK_TABLE(table), dialog->colorcb, 1,2,0,1);
272 label = gtk_label_new (_("Size:"));
273 gtk_misc_set_alignment(GTK_MISC(label),0,0);
274 gtk_table_attach(GTK_TABLE(table), label, 0,1,1,2, GTK_FILL,0,0,0);
276 dialog->textsizecb = gschem_integer_combo_box_new();
277 gschem_integer_combo_box_set_value(dialog->textsizecb, 12);
278 gtk_table_attach_defaults(GTK_TABLE(table), dialog->textsizecb, 1,2,1,2);
280 label = gtk_label_new (_("Alignment:"));
281 gtk_misc_set_alignment(GTK_MISC(label),0,0);
282 gtk_table_attach(GTK_TABLE(table), label, 0,1,2,3, GTK_FILL,0,0,0);
284 dialog->aligncb = gschem_alignment_combo_new ();
285 gschem_alignment_combo_set_align(dialog->aligncb, LOWER_LEFT);
286 gtk_table_attach_defaults(GTK_TABLE(table), dialog->aligncb, 1,2,2,3);
288 label = gtk_label_new (_("Rotation:"));
289 gtk_misc_set_alignment(GTK_MISC(label),0,0);
290 gtk_table_attach(GTK_TABLE(table), label, 0,1,3,4, GTK_FILL,0,0,0);
292 dialog->rotatecb = gschem_rotation_combo_new ();
293 gschem_rotation_combo_set_angle(dialog->rotatecb, 0);
294 gtk_table_attach_defaults(GTK_TABLE(table), dialog->rotatecb, 1,2,3,4);
297 viewport1 = gtk_viewport_new (NULL, NULL);
298 gtk_widget_show (viewport1);
300 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
301 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
302 GTK_POLICY_AUTOMATIC,
303 GTK_POLICY_AUTOMATIC);
304 gtk_container_add (GTK_CONTAINER (viewport1), scrolled_window);
305 gtk_box_pack_start( GTK_BOX(vbox), viewport1, TRUE, TRUE, 0);
307 dialog->text_view = gtk_text_view_new();
308 gtk_text_view_set_editable(GTK_TEXT_VIEW(dialog->text_view), TRUE);
309 select_all_text_in_textview(GTK_TEXT_VIEW(dialog->text_view));
311 /* Set the tab width, using pango tab array */
312 /*! \bug FIXME: This doesn't work. Why? */
313 tab_array = pango_tab_array_new (1, TRUE);
314 real_tab_width = text_view_calculate_real_tab_width(GTK_TEXT_VIEW(dialog->text_view),
315 tab_in_chars);
316 if (real_tab_width >= 0) {
317 pango_tab_array_set_tab (tab_array, 0, PANGO_TAB_LEFT, real_tab_width);
318 /* printf("Real tab width: %i\n", real_tab_width);*/
319 gtk_text_view_set_tabs (GTK_TEXT_VIEW (dialog->text_view),
320 tab_array);
322 else {
323 g_warning ("text_input_dialog: Impossible to set tab width.\n");
326 pango_tab_array_free (tab_array);
327 gtk_container_add(GTK_CONTAINER(scrolled_window), dialog->text_view);
332 /*! \brief Get/register NewText type.
334 GType newtext_get_type()
336 static GType type = 0;
338 if (type == 0) {
339 static const GTypeInfo info = {
340 sizeof(NewTextClass),
341 NULL, /* base_init */
342 NULL, /* base_finalize */
343 (GClassInitFunc) newtext_class_init,
344 NULL, /* class_finalize */
345 NULL, /* class_data */
346 sizeof(NewText),
347 0, /* n_preallocs */
348 (GInstanceInitFunc) newtext_init,
351 type = g_type_register_static (GSCHEM_TYPE_DIALOG, "NewText", &info, 0);
354 return type;
359 /*! \brief Open the dialog box to add new text
361 * \par Function Description
362 * This function creates or raises the modal text entry dialog
364 * \param [in] w_current The gschem toplevel
366 void
367 text_input_dialog (GschemToplevel *w_current)
369 if (w_current->tiwindow == NULL) {
370 /* dialog not created yet */
371 w_current->tiwindow = g_object_new (TYPE_NEWTEXT,
372 /* GtkContainer */
373 "border-width", DIALOG_BORDER_SPACING,
374 /* GtkWindow */
375 "title", _("Text Entry..."),
376 "default-width", 320,
377 "default-height", 350,
378 "window-position", GTK_WIN_POS_MOUSE,
379 "allow-grow", TRUE,
380 "allow-shrink", FALSE,
381 "modal", FALSE,
382 /* GtkDialog */
383 "has-separator", TRUE,
384 /* GschemDialog */
385 "settings-name", "text-entry",
386 "gschem-toplevel", w_current,
387 NULL);
389 gtk_window_set_transient_for (GTK_WINDOW (w_current->tiwindow),
390 GTK_WINDOW (w_current->main_window));
392 gschem_integer_combo_box_set_model (NEWTEXT (w_current->tiwindow)->textsizecb,
393 gschem_toplevel_get_text_size_list_store (w_current));
395 gtk_widget_show_all (w_current->tiwindow);
397 else {
398 /* dialog already created */
399 gtk_window_present (GTK_WINDOW(w_current->tiwindow));
402 /* always select the text in the entry */
403 select_all_text_in_textview (GTK_TEXT_VIEW (NEWTEXT (w_current->tiwindow)->text_view));
404 gtk_widget_grab_focus (NEWTEXT (w_current->tiwindow)->text_view);