Example: Text Editor

Now let us make a tiny text editor. We are ready to handle the text widget, the scroll bar, the menu, and the file selection (FS hereafter, among this section), and combinate them.

This look (below) is a copy which has been in the chapter of the menu.

When we select `Open' or `Save' in the menu, the FS dialogue appears.

Bold part is added to the program in the chapter of the menu.

Program textedit.rb:

require 'gtk'

window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)

mbar = Gtk::MenuBar.new
filemitem = Gtk::MenuItem.new('File')
filemitem.show
filemenu = Gtk::Menu.new
item1 = Gtk::MenuItem.new('Open')
item1.show
filemenu.add item1
item2 = Gtk::MenuItem.new('Save')
item2.show
filemenu.add item2
item3 = Gtk::MenuItem.new('Quit')
item3.show
filemenu.add item3
filemitem.set_submenu filemenu
mbar.append filemitem
mbar.show

vadj = Gtk::Adjustment.new(0,0,0,0,0,0)
text = Gtk::Text.new(nil, vadj)
vs = Gtk::VScrollbar.new(vadj)
text.set_editable true

hbox = Gtk::HBox.new(false, 0)
hbox.pack_start text, true, true, 0
hbox.pack_start vs, false, false, 0

vbox = Gtk::VBox.new(false, 0)
vbox.pack_start mbar, false, false, 0
vbox.pack_start hbox, true, true, 0
vbox.show

fs = Gtk::FileSelection.new('')
fs.ok_button.signal_connect('clicked') {
  fs.hide
  $callback.call fs.get_filename
}
fs.cancel_button.signal_connect('clicked') {
  fs.hide
}

item1.signal_connect('activate') {
  fs.set_title 'Open File'
  $callback = proc {|filename|
    text.set_point 0
    text.forward_delete text.get_length
    open(filename) {|f| text.insert_text f.read, 0}
  }
  fs.show
}
item2.signal_connect('activate') {
  fs.set_title 'Save File'
  $callback = proc {|filename|
    open(filename, 'w+') {|f| f.write(text.get_chars 0, -1)}
  }
  fs.show
}

item3.signal_connect('activate') {
  exit
}

window.add vbox
text.show
vs.show
hbox.show
window.show
Gtk.main

Explanation of the program above:

fs = Gtk::FileSelection.new('')
At first, a new FS widget is made here. This FS is for common use with `Open' and `Save'. So at this time, this FS is titleless, and is not displayed.
fs.ok_button.signal_connect('clicked') {
  fs.hide
  $callback.call fs.get_filename
}
Here we define the `ok' handler, which works when the `OK' button of the FS clicked. By the click:
fs.cancel_button.signal_connect('clicked') {
  fs.hide
}
Here we define the `cancel' handler, which works when the `Cancel' button of the FS clicked.
Only what it does is to hide the FS.
item1.signal_connect('activate') {
  fs.set_title 'Open File'
  $callback = proc {|filename|
    text.set_point 0
    text.forward_delete text.get_length
    open(filename) {|f| text.insert_text f.read, 0}
  }
  fs.show
}
Next to define is the `open' signal handler, when `Open' in the menu is selected. It sets the title of the FS as 'Open File', substitutes the procedure of the case when `OK' button is pushed for the global variable `$callback', and displays the FS (which should be generated).
The inside of the procedure of `$callback' is:
item2.signal_connect('activate') {
  fs.set_title 'Save File'
  $callback = proc {|filename|
    open(filename, 'w+') {|f| f.write(text.get_chars 0, -1)}
  }
  fs.show
}
And last, we define the `save' signal handler, when `Save' in the menu is selected. It sets the title of the FS as 'Save File', and substitutes the procedure of the case when `OK' button is pushed for the global variable `$callback', and displays the FS.
The inside of the procedure of `$callback' is:

Next


[TOP]
Written by akaishi@ruby.freak.ne.jp