Problem
In Part 1 and Part 2, you have highlighted enclosing curly brackets in a GtkTextView.
We will make one more improvement in this article. When the user moves the cursor with the mouse or arrow keys, the highlight will automatically disappear as shown below:
Solution
- Detect keypress with GtkWidget::key-press-event()
- Detect mouse movement with GtkWidget::button-press-event()
- We remove the highlight with GtkTextbuffer::remove_tag().
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 60 61 62 63 64 65 66 68 69 70 71 72 73 76 78 79 80 81 82 83 84 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 107 109 110 111 112 113 114 115 120 121 122 123 124 125 126 127 129 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 148 149 150 151 152 153 154 155 156 157 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | <?php $window = new GtkWindow(); $window->set_size_request(400, 240); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Find matching curly bracket - Part 3\n". "The highlight will disappear\n". "when you move the cursor with mouse or keypress"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 60); $title->set_justify(Gtk::JUSTIFY_CENTER); $alignment = new GtkAlignment(0.5, 0.5, 0, 0); $alignment->add($title); $vbox->pack_start($alignment); $left_start_iter = $left_end_iter = null; $right_start_iter = $right_end_iter = null; // Create a new buffer and a new view to show the buffer. $buffer = new GtkTextBuffer(); $buffer->set_text('if ($i==1) { test(); } else { test2(); }'); $view = new GtkTextView(); $view->set_buffer($buffer); $view->modify_font(new PangoFontDescription("Arial 10")); $view->set_wrap_mode(Gtk::WRAP_WORD); $view->connect('button-press-event', 'on_button_press_in_textview'); // note 1 $view->connect('key-press-event', 'on_key_press_in_textview'); // note 2 $hbox = new GtkHBox(); $hbox->pack_start($button = new GtkButton('Find enclosing bracket'), 0); $vbox->pack_start($hbox, 0); $button->connect('clicked', 'on_button', $buffer); $scrolled_win = new GtkScrolledWindow(); $scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); $vbox->pack_start($scrolled_win); $scrolled_win->add($view); $tag_table = $buffer->get_tag_table(); $tag['highlight'] = new GtkTextTag(); $tag['highlight']->set_property('background', "#ffff00"); $tag_table->add($tag['highlight']); $window->show_all(); Gtk::main(); function find_left_bracket($iter, $buffer) { global $tag; $iter2 = $iter->copy(); $match_start = $iter->copy(); $match_end = $iter->copy(); // check left { first $found = $iter->backward_search('{', 0, $match_start, $match_end, null); if (!$found) return null; // check if there's a } on the left $match_start2 = $iter->copy(); $match_end2 = $iter->copy(); $found2 = $iter2->backward_search('}', 0, $match_start2, $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=1) return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end); return array($match_start, $match_end); } function find_right_bracket($iter, $buffer) { global $tag; $iter2 = $iter->copy(); $match_start = $iter->copy(); $match_end = $iter->copy(); // check right } first $found = $iter->forward_search('}', 0, $match_start, $match_end, null); if (!$found) return null; // check if there's a { on the left $match_start2 = $iter->copy(); $match_end2 = $iter->copy(); $found2 = $iter2->forward_search('{', 0, $match_start2, $match_end2, null); if ($found2 && $match_start->compare($match_start2)!=-1) return null; $buffer->apply_tag($tag['highlight'], $match_start, $match_end); return array($match_start, $match_end); } function on_button($button, $buffer) { global $view, $tag; $cursor_pos = $buffer->get_mark('insert'); $iter = $buffer->get_iter_at_mark($cursor_pos); $last_pos = $buffer->create_mark('last_pos', $iter, false); global $left_start_iter, $left_end_iter; global $right_start_iter, $right_end_iter; list($left_start_iter, $left_end_iter) = find_left_bracket($iter, $buffer); if ($left_start_iter==null) return; list($right_start_iter, $right_end_iter) = find_right_bracket($iter, $buffer); if ($right_start_iter==null) return; $view->scroll_mark_onscreen($last_pos); $view->grab_focus(); } function on_button_press_in_textview($widget, $event) { remove_highlight(); } function on_key_press_in_textview($widget, $event) { remove_highlight(); } function remove_highlight() { global $buffer, $tag; global $left_start_iter, $left_end_iter; global $right_start_iter, $right_end_iter; if ($left_start_iter==null || $left_end_iter==null) return; // note 3 if ($right_start_iter==null || $right_end_iter==null) return; // note 3 $buffer->remove_tag($tag['highlight'], $left_start_iter, $left_end_iter); // note 4 $buffer->remove_tag($tag['highlight'], $right_start_iter, $right_end_iter); // note 4 } ?> |
Output
As shown above.Explanation
- Detect mouse movement.
- Detect keypress.
- Check if there's any existing highlight.
- If there is, remove the highlight!
Related Links
- How to highlight matching brackets in GtkTextView - Part 1?
- How to highlight matching brackets in GtkTextView - Part 2?
- How to highlight matching html tags in GtkTextView?
- How to apply styles to GtkTextView using GtkTextTag - Part 1?
- How to search for text in GtkTextView - Part 1?
- How to search for text in GtkTextView - Part 2?
- How to search for text in GtkTextView - Part 3?
Read more...