Problem
I've showed you how to apply styles to GtkTextView / GtkTextBuffer (e.g. bold, italic, underline, font color and highlight) in How to apply styles to GtkTextView using GtkTextTag - Part 1?
This article shows you how to toggle these styles on and off using the same format buttons as shown below.
Note: This sample code in this article is contributed by Dysmas. It's a follow-up of another sample code contributed by him: How to have a popup textview for editing of long text?
Solution
- First we need to test if there's any existing style within user's highlighted text with the following methods:
- If there is no style applied, we add the style with GtkTextbuffer::apply_tag().
- If the style is already there, we remove it with GtkTextbuffer::remove_tag().
Sample Code
1 2 3 4 5 6 9 10 11 12 13 14 15 16 17 18 19 20 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 53 55 56 57 58 59 60 61 63 64 65 66 67 68 69 70 71 72 73 74 75 77 78 80 81 83 84 86 87 88 89 90 99 100 101 | <?php $window = new GtkWindow(); $window->set_title($argv[0]); $window->set_size_request(400, 240); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // define menu definition $toolbar_definition = array('Bold', 'Italic', 'Underline', '<hr>', 'Blue', '<hr>', 'Highlight'); setup_toolbar($vbox, $toolbar_definition); // Create a new buffer and a new view to show the buffer. $buffer = new GtkTextBuffer(); $view = new GtkTextView(); $view->set_buffer($buffer); $view->modify_font(new PangoFontDescription("Arial 12")); $view->set_wrap_mode(Gtk::WRAP_WORD); $vbox->pack_start($view); $view->grab_focus(); $tag_table = $buffer->get_tag_table(); $tag['Bold'] = new GtkTextTag(); $tag['Bold']->set_property('weight', Pango::WEIGHT_BOLD); $tag_table->add($tag['Bold']); $tag['Italic'] = new GtkTextTag(); $tag['Italic']->set_property('style', Pango::STYLE_ITALIC); $tag_table->add($tag['Italic']); $tag['Underline'] = new GtkTextTag(); $tag['Underline']->set_property('underline', Pango::UNDERLINE_SINGLE); $tag_table->add($tag['Underline']); $tag['Blue'] = new GtkTextTag(); $tag['Blue']->set_property('foreground', "#0000ff"); $tag_table->add($tag['Blue']); $tag['Highlight'] = new GtkTextTag(); $tag['Highlight']->set_property('background', "#ffff00"); $tag_table->add($tag['Highlight']); $window->show_all(); Gtk::main(); // setup toolbar function setup_toolbar($vbox, $toolbar_definition) { $toolbar = new GtkToolBar(); $vbox->pack_start($toolbar, 0, 0); foreach($toolbar_definition as $item) { if ($item=='<hr>') { $toolbar->insert(new GtkSeparatorToolItem(), -1); } else { $stock_image_name = 'Gtk::STOCK_'.strtoupper($item); if (defined($stock_image_name)) { $toolbar_item = GtkToolButton::new_from_stock(constant($stock_image_name)); } else { $toolbar_item = new GtkToolButton(); // no stock item $toolbar_item->set_label("\n".$item); // just display the text label } $toolbar->insert($toolbar_item, -1); $toolbar_item->connect('clicked', 'on_toolbar_button', $item); } } } // process toolbar function on_toolbar_button($button, $item) { global $buffer, $tag; echo "toolbar clicked: $item\n"; list($start, $end) = $buffer->get_selection_bounds(); if ($start==null || $end==null) return; // no selection if (($start->has_tag($tag[$item]) && $end->has_tag($tag[$item])) || // note 1 ($start->has_tag($tag[$item]) && $end->ends_tag($tag[$item]))) { $buffer->remove_tag($tag[$item], $start, $end); // note 2 } else { $buffer->apply_tag($tag[$item], $start, $end); // note 3 } } ?> |
Output
As shown above.Explanation
We make use of the code in How to set up toolbar? to display the toolbar.
What's new here:
- Selection already contains the style?
- Yes, remove it.
- No, apply the style.
Note
The sample code above only performs bold. When you press the bold button on a "bolded" text, it doesn't unbold. We will improve on this in Part 2.
Read more...