470. How to have a popup textview for editing of long text?

Problem

Dysmas sent me this interesting and very useful sample code that allows you to have a popup textview for editing of long text.

For example, you have set up a form that prompts the user for feedback as shown below.

If the user wants to enter a lot of text in the comments field (e.g. he would like to attach some sample codes), he can double click in the comments field which will popup a bigger textview for him to enter.

By default, a double click in a textview will select and highlight a word. You might want to see from this example how to intercept the double-click to popup the textview in a dialog box.

How to have a popup textview for editing of long text?


Solution

  • We make use of the technique from How to align GtkEntry fields - Part 2? to display the form.
  • By default, a double click in a textview will select and highlight a word. In addition to using button-press-event to intercept the double-click, you also need to use the method emit_stop_by_name('button-press-event') to stop the default actions.

Important Note: This only works for PHP-GTK2 compliled with gtk+ v2.10 and above. If you are using an older version, for linux, you may follow the step-by-step instructions to recompile php-gtk2 with gtk+ v2.10. For windows, please refer to How to install php gtk2 on windows? You may also want to take a look here to see some of the new exciting PHP-GTK2 Functionalities.


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
15   
16   
17   
18   
19   
20   
21   
22   
23   
24   
25   
26   
27   
28   
29   
30   
32   
33   
34   
35   
36   
37   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
56   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
68   
70   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
91   
92   
93   
94   
95   
97   
98   
99   
100   
101   
102   
103   
104   
105   
106   
107   
108   
109   
110   
111   
112   
113   
114   
115   
116   
118   
121   
122   
123   
124   
125   
126   
127   
128   
129   
130   
131   
132   
133   
134   
135   
136   
137   
138   
139   
143   
144   
145   
146   
147   
148   
149   
150   
151   
152   
153   
154   
155   
156   
157   
158   
159   
160   
161   
162   
163   
164   
165   
166   
167   
168   
169   
170   
171   
172   
173   
174   
175   
176   
177   
<?php
$window = new GtkWindow();
$window->set_title($argv[0]);
$window->set_size_request(400, 280);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Have a popup textview for editing of long text");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 40);
$vbox->pack_start($title, 0, 0);

$fields = array('Name', 'Email', 'Comments');
$field_size = array(240, 120, 0);
$entry = array(); // to store the text entries

$table = new GtkTable();
display_table($table, $fields, $field_size); // display the table
$vbox->pack_start($table);

function display_table($table, $fields, $field_size) {
    global $entry;
    $row = 0;
    foreach ($fields as $field) {
        $label = new GtkLabel("  $field: ");
        $alignment = new GtkAlignment(1, 0, 0, 0);
        $alignment->add($label);
        $table->attach($alignment, 0, 1, $row, $row+1);

        if ($field=='Comments') {
            $buffer = new GtkTextBuffer();
            global $view;
            $view = new GtkTextView();
            $view->set_buffer($buffer);
            $view->set_wrap_mode(Gtk::WRAP_WORD);
            $view->set_size_request(280, 80);
            $view->connect('button-press-event', 'on_view_button_press'); // note 1
            $entry[$row] = new GtkVBox();
            $entry[$row]->pack_start($view, 0);
            $entry[$row]->pack_start(
                new GtkLabel('Double-click for bigger text-edit window'));


        } else {
            $entry[$row] = new GtkEntry();
            $entry[$row]->set_size_request($field_size[$row], -1);
        }
        $alignment = new GtkAlignment(0, 0, 0, 0);
        $alignment->add($entry[$row]);
        $table->attach($alignment, 1, 2, $row, $row+1);
        ++$row;
    }
}

// create a submit button
$button = new GtkButton('Submit');
$button->set_size_request(60, 28);
$button->connect('clicked', 'on_click');
$row = count($fields);
$alignment = new GtkAlignment(0, 0.5, 0, 0);
$alignment->add($button);
$table->attach($alignment, 1, 2, $row, $row+1);

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

function on_click($button) {
    global $fields, $entry;
    $i=0;
    foreach($fields as $field) {
        if ($field=='Comments') {
            global $view;
            $buffer = $view->get_buffer();
            $input = $buffer->get_text($buffer->get_start_iter(),
                $buffer->get_end_iter());
        } else {
            $input = $entry[$i]->get_text();
        }
        echo "$field: $input\n";
        ++$i;
    }
}

function on_view_button_press($widget, $event) {
     if ($event->type==Gdk::_2BUTTON_PRESS) {
         print "bp201. double-click!\n";
         $zoom = new zoom($widget); // note 2
         $widget->emit_stop_by_name('button-press-event'); // note 3
         return true;
     } else {
         return false;
     }
}

function zoom($widget) {
    $zoom = new zoom($widget);
}

class zoom{

    var $entry;
    var $ok=0;
    var $buff;

    function zoom($view) {
        $dialog = new GtkDialog('Zoom', null,
            Gtk::DIALOG_MODAL|Gtk::DIALOG_NO_SEPARATOR);
        $dialog->set_size_request(400, 300);
        // $label = new GtkLabel($label: ");
        // $dialog->vbox->pack_start($label);

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

        $buffer = $view->get_buffer();
        $view_copy = new GtkTextView();
        $buffer_copy = new GtkTextBuffer();
        $buffer_copy->set_text($buffer->get_text(
            $buffer->get_start_iter(), $buffer->get_end_iter()));
        $view_copy->set_buffer($buffer_copy);
        $scrolled_win->add($view_copy);

        $this->buffer = $buffer;
        $this->buffer_copy = $buffer_copy;

        $button_save = new GtkButton('Save');
        $button_discard = new GtkButton('Discard');
        $button_save->connect('clicked', array($this, 'on_button_save'));
        $button_discard->connect('clicked', array($this, 'on_button_discard'));
        $button_save->set_size_request(80, -1);
        $button_discard->set_size_request(80, -1);

        $hbox = new GtkHBox();
        $dialog->vbox->pack_start($hbox, 0);
        $hbox->pack_start(new GtkLabel());
        $hbox->pack_start($button_save, 0);
        $hbox->pack_start(new GtkLabel(' '), 0);
        $hbox->pack_start($button_discard, 0);

        $dialog->action_area->set_size_request(-1, 1);
        $this->dialog = $dialog;
        $dialog->show_all();
        $dialog->run();
        $dialog->destroy();
    }

    function on_button_save($button) {
        $this->buffer->set_text($this->buffer_copy->get_text(
            $this->buffer_copy->get_start_iter(),
            $this->buffer_copy->get_end_iter()));
        $this->dialog->destroy();
    }

    function on_button_discard($button) {
        $this->dialog->destroy();
    }

}

?>

Output

As shown above.

 

Explanation

  1. Intercept the double-click.
  2. Popup the textview in a dialog box.
  3. Stop any default actions.

Related Links

Add comment


Security code
Refresh