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
21 * \file gschem_text_properties_dockable.c
23 * \brief A dockable for editing text properties
37 #include <gdk/gdkkeysyms.h>
39 #include "../include/gschem_text_properties_dockable.h"
43 adjust_focus (GschemDockable
*parent
);
46 class_init (GschemTextPropertiesDockableClass
*klass
);
49 create_text_content_section (GschemTextPropertiesDockable
*widget
);
52 create_text_property_section (GschemTextPropertiesDockable
*widget
);
55 dispose (GObject
*object
);
58 create_widget (GschemDockable
*parent
);
61 set_selection_adapter (GschemTextPropertiesDockable
*widget
, GschemSelectionAdapter
*adapter
);
64 update_text_alignment_model (GschemTextPropertiesDockable
*widget
);
67 update_text_alignment_widget (GschemTextPropertiesDockable
*widget
);
70 update_text_color_model (GschemTextPropertiesDockable
*widget
);
73 update_text_color_widget (GschemTextPropertiesDockable
*widget
);
76 update_text_content_model (GschemTextPropertiesDockable
*widget
);
79 update_text_content_widget (GschemTextPropertiesDockable
*widget
);
82 update_text_rotation_model (GschemTextPropertiesDockable
*widget
);
85 update_text_rotation_widget (GschemTextPropertiesDockable
*widget
);
89 /*! \brief Adjust widget focus for the convienence of the user
91 * If selecting one item, this function selects all the text content and gives
92 * focus to the text view. If multiple items are selected, this function gives
93 * focus to the color combo box.
95 * \param [in] widget This text properties widget
98 adjust_focus (GschemDockable
*parent
)
100 GschemTextPropertiesDockable
*widget
=
101 GSCHEM_TEXT_PROPERTIES_DOCKABLE (parent
);
103 g_return_if_fail (widget
!= NULL
);
104 g_return_if_fail (widget
->text_view
!= NULL
);
105 g_return_if_fail (widget
->colorcb
!= NULL
);
107 if (gtk_widget_is_sensitive (widget
->text_view
)) {
108 select_all_text_in_textview (GTK_TEXT_VIEW (widget
->text_view
));
109 gtk_widget_grab_focus (widget
->text_view
);
112 gtk_widget_grab_focus (widget
->colorcb
);
118 /*! \brief Get/register text properties widget type.
121 gschem_text_properties_dockable_get_type ()
123 static GType type
= 0;
126 static const GTypeInfo info
= {
127 sizeof(GschemTextPropertiesDockableClass
),
128 NULL
, /* base_init */
129 NULL
, /* base_finalize */
130 (GClassInitFunc
) class_init
,
131 NULL
, /* class_finalize */
132 NULL
, /* class_data */
133 sizeof(GschemTextPropertiesDockable
),
135 NULL
, /* instance_init */
138 type
= g_type_register_static (GSCHEM_TYPE_DOCKABLE
,
139 "GschemTextPropertiesDockable",
150 * \brief Initialize the text properties widget class structure
155 class_init (GschemTextPropertiesDockableClass
*klass
)
157 GObjectClass
*object_class
;
159 g_return_if_fail (klass
!= NULL
);
161 GSCHEM_DOCKABLE_CLASS (klass
)->create_widget
= create_widget
;
162 GSCHEM_DOCKABLE_CLASS (klass
)->post_present
= adjust_focus
;
164 object_class
= G_OBJECT_CLASS (klass
);
166 g_return_if_fail (object_class
!= NULL
);
168 object_class
->dispose
= dispose
;
174 * \brief Create the text content section widget
177 * \return The new text content section widget
180 create_text_content_section (GschemTextPropertiesDockable
*widget
)
182 GtkWidget
*bbox
= gtk_hbutton_box_new ();
183 GtkWidget
*scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
184 GtkWidget
*vbox
= gtk_vbox_new (FALSE
, 0);
186 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
187 GTK_POLICY_AUTOMATIC
,
188 GTK_POLICY_AUTOMATIC
);
190 widget
->text_view
= gtk_text_view_new ();
192 gtk_text_view_set_editable (GTK_TEXT_VIEW (widget
->text_view
), TRUE
);
194 /*! \bug FIXME: Set tab's width in the textview widget. */
195 /* See first the code in text_input_dialog and get it working before adding
199 gtk_container_add (GTK_CONTAINER (scrolled
), widget
->text_view
);
201 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox
), GTK_BUTTONBOX_END
);
203 widget
->apply_button
= gtk_button_new_from_stock (GTK_STOCK_APPLY
);
205 g_signal_connect_swapped (G_OBJECT (widget
->apply_button
),
207 G_CALLBACK (update_text_content_model
),
210 gtk_box_pack_start (GTK_BOX (bbox
), /* box */
211 widget
->apply_button
, /* child */
216 gtk_box_set_spacing (GTK_BOX (vbox
), DIALOG_V_SPACING
);
218 gtk_box_pack_start (GTK_BOX (vbox
), /* box */
219 scrolled
, /* child */
224 gtk_box_pack_start (GTK_BOX (vbox
), /* box */
230 return gschem_dialog_misc_create_section_widget (_("<b>Text Content</b>"), vbox
);
236 * \brief Create the text property section widget
239 * \return The new text property section widget
242 create_text_property_section (GschemTextPropertiesDockable
*widget
)
246 GtkWidget
*editor
[4];
248 label
[0] = gschem_dialog_misc_create_property_label(_("Color:"));
249 label
[1] = gschem_dialog_misc_create_property_label(_("Size:"));
250 label
[2] = gschem_dialog_misc_create_property_label(_("Alignment:"));
251 label
[3] = gschem_dialog_misc_create_property_label(_("Rotation:"));
253 editor
[0] = widget
->colorcb
= x_colorcb_new ();
254 editor
[1] = widget
->textsizecb
= gschem_integer_combo_box_new ();
255 editor
[2] = widget
->aligncb
= gschem_alignment_combo_new();
256 editor
[3] = widget
->rotatecb
= gschem_rotation_combo_new();
258 table
= gschem_dialog_misc_create_property_table (label
, editor
, 4);
260 widget
->bindings
= g_slist_append (widget
->bindings
,
261 gschem_binding_integer_new ("text-size",
264 g_signal_connect_swapped (G_OBJECT (widget
->colorcb
),
266 G_CALLBACK (update_text_color_model
),
269 g_signal_connect_swapped (G_OBJECT (widget
->aligncb
),
271 G_CALLBACK (update_text_alignment_model
),
274 g_signal_connect_swapped (G_OBJECT (widget
->rotatecb
),
276 G_CALLBACK (update_text_rotation_model
),
279 return gschem_dialog_misc_create_section_widget (_("<b>Text Properties</b>"), table
);
287 * \param [in] object The text edit widget to dispose
290 dispose (GObject
*object
)
292 GschemTextPropertiesDockable
*widget
;
293 GschemTextPropertiesDockableClass
*klass
;
294 GObjectClass
*parent_class
;
296 g_return_if_fail (object
!= NULL
);
298 widget
= GSCHEM_TEXT_PROPERTIES_DOCKABLE (object
);
300 set_selection_adapter (widget
, NULL
);
302 g_slist_foreach (widget
->bindings
, (GFunc
) g_object_unref
, NULL
);
303 g_slist_free (widget
->bindings
);
304 widget
->bindings
= NULL
;
306 /* lastly, chain up to the parent dispose */
308 klass
= GSCHEM_TEXT_PROPERTIES_DOCKABLE_GET_CLASS (object
);
309 g_return_if_fail (klass
!= NULL
);
310 parent_class
= g_type_class_peek_parent (klass
);
311 g_return_if_fail (parent_class
!= NULL
);
312 parent_class
->dispose (object
);
318 * \brief Create text property widgets and set up property change
321 * \param [in,out] parent This dockable
324 create_widget (GschemDockable
*parent
)
326 GschemTextPropertiesDockable
*widget
=
327 GSCHEM_TEXT_PROPERTIES_DOCKABLE (parent
);
328 GschemToplevel
*w_current
= parent
->w_current
;
334 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
336 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
338 GTK_POLICY_AUTOMATIC
);
340 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
343 viewport
= gtk_viewport_new (NULL
, NULL
);
344 gtk_container_add (GTK_CONTAINER (scrolled
), viewport
);
346 gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport
),
349 vbox
= gtk_vbox_new (FALSE
, DIALOG_V_SPACING
);
350 gtk_container_set_border_width (GTK_CONTAINER (vbox
), DIALOG_BORDER_SPACING
);
351 gtk_container_add (GTK_CONTAINER (viewport
), vbox
);
353 gtk_box_pack_start (GTK_BOX (vbox
), /* box */
354 create_text_content_section (widget
), /* child */
359 gtk_box_pack_start (GTK_BOX (vbox
), /* box */
360 create_text_property_section (widget
), /* child */
366 gschem_integer_combo_box_set_model (widget
->textsizecb
,
367 gschem_toplevel_get_text_size_list_store (w_current
));
369 set_selection_adapter (widget
,
370 gschem_toplevel_get_selection_adapter (w_current
));
373 gtk_widget_show_all (scrolled
);
380 * \brief Set the selection that this widget manipulates
382 * \param [in,out] widget This widget
383 * \param [in] selection The selection to manipulate
386 set_selection_adapter (GschemTextPropertiesDockable
*widget
, GschemSelectionAdapter
*adapter
)
388 g_return_if_fail (widget
!= NULL
);
390 if (widget
->adapter
!= NULL
) {
391 g_signal_handlers_disconnect_by_func (widget
->adapter
,
392 G_CALLBACK (update_text_content_widget
),
395 g_signal_handlers_disconnect_by_func (widget
->adapter
,
396 G_CALLBACK (update_text_rotation_widget
),
399 g_signal_handlers_disconnect_by_func (widget
->adapter
,
400 G_CALLBACK (update_text_color_widget
),
403 g_signal_handlers_disconnect_by_func (widget
->adapter
,
404 G_CALLBACK (update_text_alignment_widget
),
407 g_object_unref (widget
->adapter
);
410 widget
->adapter
= adapter
;
412 g_slist_foreach (widget
->bindings
,
413 (GFunc
) gschem_binding_set_model_object
,
416 if (widget
->adapter
!= NULL
) {
417 g_object_ref (widget
->adapter
);
419 g_signal_connect_swapped (widget
->adapter
,
420 "notify::text-alignment",
421 G_CALLBACK (update_text_alignment_widget
),
424 g_signal_connect_swapped (widget
->adapter
,
425 "notify::text-color",
426 G_CALLBACK (update_text_color_widget
),
429 g_signal_connect_swapped (widget
->adapter
,
430 "notify::text-rotation",
431 G_CALLBACK (update_text_rotation_widget
),
434 g_signal_connect_swapped (widget
->adapter
,
435 "notify::text-string",
436 G_CALLBACK (update_text_content_widget
),
439 update_text_alignment_widget (widget
);
440 update_text_color_widget (widget
);
441 update_text_rotation_widget (widget
);
442 update_text_content_widget (widget
);
449 * \brief Update the text alignment in the model
451 * \param [in,out] widget This widget
454 update_text_alignment_model (GschemTextPropertiesDockable
*widget
)
456 g_return_if_fail (widget
!= NULL
);
457 g_return_if_fail (widget
->aligncb
!= NULL
);
459 if (widget
->adapter
!= NULL
) {
460 int alignment
= gschem_alignment_combo_get_align (widget
->aligncb
);
462 if (alignment
>= 0) {
463 gschem_selection_adapter_set_text_alignment (widget
->adapter
, alignment
);
471 * \brief Update the value in the text alignment widget
473 * \param [in,out] widget This widget
476 update_text_alignment_widget (GschemTextPropertiesDockable
*widget
)
478 g_return_if_fail (widget
!= NULL
);
479 g_return_if_fail (widget
->aligncb
!= NULL
);
481 if (widget
->adapter
!= NULL
) {
482 int alignment
= gschem_selection_adapter_get_text_alignment (widget
->adapter
);
484 g_signal_handlers_block_by_func (G_OBJECT (widget
->aligncb
),
485 G_CALLBACK (update_text_alignment_model
),
488 gschem_alignment_combo_set_align (widget
->aligncb
, alignment
);
490 g_signal_handlers_unblock_by_func (G_OBJECT (widget
->aligncb
),
491 G_CALLBACK (update_text_alignment_model
),
494 gtk_widget_set_sensitive (GTK_WIDGET (widget
->aligncb
), (alignment
!= NO_SELECTION
));
501 * \brief Update the text color value in the model
503 * \param [in,out] widget This widget
506 update_text_color_model (GschemTextPropertiesDockable
*widget
)
508 g_return_if_fail (widget
!= NULL
);
509 g_return_if_fail (widget
->colorcb
!= NULL
);
511 if (widget
->adapter
!= NULL
) {
512 int color
= x_colorcb_get_index (widget
->colorcb
);
515 gschem_selection_adapter_set_text_color (widget
->adapter
, color
);
523 * \brief Update the value in the object color widget
525 * \param [in,out] widget This widget
528 update_text_color_widget (GschemTextPropertiesDockable
*widget
)
530 g_return_if_fail (widget
!= NULL
);
531 g_return_if_fail (widget
->colorcb
!= NULL
);
533 if (widget
->adapter
!= NULL
) {
534 int color
= gschem_selection_adapter_get_text_color (widget
->adapter
);
536 g_signal_handlers_block_by_func (G_OBJECT (widget
->colorcb
),
537 G_CALLBACK (update_text_color_model
),
540 x_colorcb_set_index(widget
->colorcb
, color
);
542 g_signal_handlers_unblock_by_func (G_OBJECT (widget
->colorcb
),
543 G_CALLBACK (update_text_color_model
),
546 gtk_widget_set_sensitive (GTK_WIDGET (widget
->colorcb
), (color
!= NO_SELECTION
));
553 * \brief Update the text string in the model
555 * \param [in,out] widget This widget
558 update_text_content_model (GschemTextPropertiesDockable
*widget
)
560 g_return_if_fail (widget
!= NULL
);
561 g_return_if_fail (widget
->text_view
!= NULL
);
563 if (widget
->adapter
!= NULL
) {
565 GtkTextBuffer
*buffer
;
569 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget
->text_view
));
570 gtk_text_buffer_get_bounds (buffer
, &start
, &end
);
571 string
= gtk_text_iter_get_text (&start
, &end
);
573 if (string
!= NULL
) {
574 gschem_selection_adapter_set_text_string (widget
->adapter
, string
, widget
->parent
.w_current
);
582 * \brief Update the value in the object color widget
584 * \param [in,out] widget This widget
587 update_text_content_widget (GschemTextPropertiesDockable
*widget
)
589 g_return_if_fail (widget
!= NULL
);
590 g_return_if_fail (widget
->text_view
!= NULL
);
592 if (widget
->adapter
!= NULL
) {
593 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget
->text_view
));
594 const char *string
= gschem_selection_adapter_get_text_string (widget
->adapter
);
596 g_signal_handlers_block_by_func (G_OBJECT (widget
->text_view
),
597 G_CALLBACK (update_text_content_model
),
600 if (string
!= NULL
) {
601 gtk_text_buffer_set_text (buffer
, string
, -1);
607 gtk_text_buffer_get_bounds (buffer
, &start
, &end
);
608 gtk_text_buffer_delete (buffer
, &start
, &end
);
611 g_signal_handlers_unblock_by_func (G_OBJECT (widget
->text_view
),
612 G_CALLBACK (update_text_content_model
),
615 gtk_widget_set_sensitive (GTK_WIDGET (widget
->text_view
), (string
!= NULL
));
616 gtk_widget_set_sensitive (GTK_WIDGET (widget
->apply_button
), (string
!= NULL
));
623 * \brief Update the text rotation value in the model
625 * \param [in,out] widget This widget
628 update_text_rotation_model (GschemTextPropertiesDockable
*widget
)
630 g_return_if_fail (widget
!= NULL
);
631 g_return_if_fail (widget
->rotatecb
!= NULL
);
633 if (widget
->adapter
!= NULL
) {
634 int angle
= gschem_rotation_combo_get_angle (widget
->rotatecb
);
637 gschem_selection_adapter_set_text_rotation (widget
->adapter
, angle
);
645 * \brief Update the value in the text rotation widget
647 * \param [in,out] widget This widget
650 update_text_rotation_widget (GschemTextPropertiesDockable
*widget
)
652 g_return_if_fail (widget
!= NULL
);
653 g_return_if_fail (widget
->rotatecb
!= NULL
);
655 if (widget
->adapter
!= NULL
) {
656 int angle
= gschem_selection_adapter_get_text_rotation (widget
->adapter
);
658 g_signal_handlers_block_by_func (G_OBJECT (widget
->rotatecb
),
659 G_CALLBACK (update_text_rotation_model
),
662 gschem_rotation_combo_set_angle (widget
->rotatecb
, angle
);
664 g_signal_handlers_unblock_by_func (G_OBJECT (widget
->rotatecb
),
665 G_CALLBACK (update_text_rotation_model
),
668 gtk_widget_set_sensitive (GTK_WIDGET (widget
->rotatecb
), (angle
!= NO_SELECTION
));