149. How to search for text in GtkTextView - Part 2?

Problem

You have set up a search field that allows user to search for text in a GtkTextView in Part 1.

You would now like to add a "Find Next" button as shown below:

How to search for text in GtkTextView - Part 2?


Solution


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
33   
34   
39   
40   
41   
42   
43   
44   
46   
47   
48   
49   
50   
51   
53   
54   
55   
56   
57   
58   
59   
61   
62   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
74   
75   
76   
77   
78   
79   
80   
<?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("Search for text in GtkTextView - Part 2\n".
"Add \"Find Next\"");
$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, 0, 0);
$alignment->add($title);
$vbox->pack_start($alignment, 0, 0);
$vbox->pack_start(new GtkLabel(), 0, 0);

$hbox = new GtkHBox();
$hbox->pack_start(new GtkLabel("Search string: "), 0);
$hbox->pack_start($entry = new GtkEntry(), 0);
$hbox->pack_start($button_search = new GtkButton('Search'), 0);
$hbox->pack_start($button_search_next = new GtkButton('Next'), 0);
$vbox->pack_start($hbox, 0);
$button_search->connect('clicked', 'on_search_button', $entry);
$button_search_next->connect('clicked', 'on_search_next_button', $entry);

// 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);

$scrolled_win = new GtkScrolledWindow();
$scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
$vbox->pack_start($scrolled_win);
$scrolled_win->add($view);

$window->show_all();
Gtk::main();

function on_search_button($button, $entry) {
    global $view, $buffer;
    $search_str = $entry->get_text();
    $start_iter = $buffer->get_start_iter(); // note 2
    search($search_str, $start_iter);
}

function on_search_next_button($button, $entry) {
    global $view, $buffer;
    $search_str = $entry->get_text();
    $last_search_pos = $buffer->get_mark('last_search_pos');
    if ($last_search_pos==null) return;

    $last_search_iter = $buffer->get_iter_at_mark($last_search_pos); // note 3
    search($search_str, $last_search_iter); // note 4
}

function search($search_str, $start_iter) {
    global $view, $buffer;
    $match_start = $buffer->get_start_iter();
    $match_end = $buffer->get_end_iter();
    $found = $start_iter->forward_search($search_str, 0, $match_start, $match_end, null);
    if ($found) {
        $buffer->select_range($match_start, $match_end);
        $buffer->create_mark('last_search_pos', $match_end, false); // note 1
    }
}

?>

Output

As shown above.
 

Explanation

We make use of the code in Part 1.

What's new here:

  1. Stores the last search position.
  2. If "Search" button is pressed, we start from the beginning of text buffer.
  3. Retrieves the last search position.
  4. If "Find Next" button is pressed, we start from the last search position.

Note

The above example has one problem. If the text found is not visible, it does not scroll to the text. We will fix this in the next article.

Related Links

Add comment


Security code
Refresh