[ruby-gnome2-doc-cvs] [Ruby-GNOME2 Project Website] create - tut-gtk2-dynui-tyu

Back to archive index

ruby-****@sourc***** ruby-****@sourc*****
2009年 3月 6日 (金) 04:34:03 JST


-------------------------
REMOTE_ADDR = 74.15.84.244
REMOTE_HOST = 
        URL = http://ruby-gnome2.sourceforge.jp/hiki.cgi?tut-gtk2-dynui-tyu
-------------------------
TITLE       = tut-gtk2-dynui-tyu
KEYWORD     = 
= Dynamic User Interfaces Built With Glade
{{link "tut-gtk2-dynui-bui", "tut-gtk2-dynui", "tut-gtk", nil}}

== Test Your Understanding

This exercise is especially important for you to become a proficient Ruby GTK+ developer. It is not practical to manually design every aspect of a large GUI application because it simply takes too long. Instead you should be using Glade to design the user interface and Libglade to load that design and connect signals. By doing this, you will be able to quickly finish the graphical aspects of your applications and get to the back-end code that makes your applications work.

In this exercise implement the text editor from the 1st exercise in chapter (9) or as we call it "Menus and Toolbars" session, where we used the simple text editor example from an even earlier chapter (7) and implemented it there with Gtk::UIManager. Here we will use Glade to d the same. The toolbar in the text editor should be now implemented completely in Glade. This exercise should not require much extra coding if you use the solution from the previous chapter. However there are few important small differences. In chapter (9) most of the callbacks were implemented as Procs which inherit variables from the environment in which they are defined. Here, however, they are all methods. This calls for a different approach to pass in the variables tucked into the TextEditor class.


Again, for your convenience I will include the ((*ex10-1-editor-tb.glade*)) file, so you can verify your work. 

((*ex10-1-editor-tb.glade*))

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
 <!--Generated with glade3 3.0.2 on Fri Dec  8 17:54:41 2006 by user @ chewy-->
 <glade-interface>
   <widget class="GtkWindow" id="window">
     <property name="default_width">600</property>
     <property name="default_height">450</property>
     <signal name="destroy" handler="gtk_main_quit"/>
     <child>
       <widget class="GtkVBox" id="vbox1">
         <property name="visible">True</property>
         <child>
           <widget class="GtkToolbar" id="toolbar1">
             <property name="visible">True</property>
             <child>
               <widget class="GtkToolButton" id="toolbutton1">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-new</property>
                 <signal name="clicked" handler="new_clicked"/>
               </widget>
             </child>
             <child>
               <widget class="GtkToolButton" id="toolbutton2">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-open</property>
                 <signal name="clicked" handler="open_clicked"/>
               </widget>
             </child>
             <child>
               <widget class="GtkToolButton" id="toolbutton3">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-save</property>
                 <signal name="clicked" handler="save_clicked"/>
               </widget>
             </child>
             <child>
               <widget class="GtkSeparatorToolItem" id="separatortoolitem1">
                 <property name="visible">True</property>
               </widget>
             </child>
             <child>
               <widget class="GtkToolButton" id="toolbutton4">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-cut</property>
                 <signal name="clicked" handler="cut_clicked"/>
               </widget>
             </child>
             <child>
               <widget class="GtkToolButton" id="toolbutton5">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-copy</property>
                 <signal name="clicked" handler="copy_clicked"/>
               </widget>
             </child>
             <child>
               <widget class="GtkToolButton" id="toolbutton6">
                 <property name="visible">True</property>
                 <property name="stock_id">gtk-paste</property>
                 <signal name="clicked" handler="paste_clicked"/>
               </widget>
             </child>
           </widget>
           <packing>
             <property name="expand">False</property>
           </packing>
         </child>
         <child>
           <widget class="GtkScrolledWindow" id="scrolledwindow1">
             <property name="visible">True</property>
             <child>
               <widget class="GtkTextView" id="textview">
                 <property name="visible">True</property>
               </widget>
             </child>
           </widget>
           <packing>
             <property name="position">1</property>
           </packing>
         </child>
         <child>
           <widget class="GtkHBox" id="hbox">
             <property name="visible">True</property>
             <property name="spacing">5</property>
             <child>
               <widget class="GtkEntry" id="entry1">
                 <property name="width_request">250</property>
                 <property name="visible">True</property>
                 <property name="text" translatable="yes">Search for ...</property>
               </widget>
               <packing>
                 <property name="expand">False</property>
               </packing>
             </child>
             <child>
               <widget class="GtkButton" id="button1">
                 <property name="visible">True</property>
                 <property name="label" translatable="yes">gtk-find</property>
                 <property name="use_stock">True</property>
                 <signal name="clicked" handler="find_clicked"/>
               </widget>
               <packing>
                 <property name="expand">False</property>
                 <property name="position">1</property>
               </packing>
             </child>
           </widget>
           <packing>
             <property name="expand">False</property>
             <property name="padding">5</property>
             <property name="position">2</property>
           </packing>
         </child>
       </widget>
     </child>
   </widget>
 </glade-interface>


Indeed, the above file or better your own Glade creation's output has to be first processed with ((*ruby-glade-create-template*)) command, and then all the missing code added to it. I hope after skimming through what we have here you will have no trouble building this yourself. Remember that by just reading the code here you will most likely miss many little things that matter. I urge you to study and play with this code until you are absolutely confident you understand how it came to being. 

Following is the Ruby program where all the callbacks are implemented.

((*ex10-1-editor-tb.rb*))

 #!/usr/bin/env ruby
 #
 # This file is gererated by ruby-glade-create-template 1.1.4.
 #
 require 'libglade2'
 
 class TextEditor
   attr_accessor :textview, :search
 end
 
 class Ex101EditorTbGlade
   include GetText
 
   attr :glade, :texteditor
   
   def initialize(path_or_data,
                  root = nil,
                  domain = nil,
                  localedir = nil,
                  flag = GladeXML::FILE)
     bindtextdomain(domain, localedir, nil, "UTF-8")
     @glade = GladeXML.new(path_or_data,
                           root,
                           domain,
                           localedir,
                           flag) {|handler| method(handler)}
     @texeditor = TextEditor.new
     @texeditor.textview = @glade["textview"]
     @texeditor.search   = @glade["entry1"]
   end
  
   def gtk_main_quit(widget)
     Gtk.main_quit
   end
 
   # Verify that the user want to create a new document.
   # If so, delete all of the text from the buffer.
   def new_clicked(widget)
     dialog = Gtk::MessageDialog.new(
         nil,
         Gtk::Dialog::MODAL,
         Gtk::MessageDialog::QUESTION,
         Gtk::MessageDialog::BUTTONS_YES_NO,
         "All changes will be lost. Do you want to continue?"
     )
     dialog.title = "Information"
     dialog.run do |r|
       @texeditor.textview.buffer.text = "" if r == Gtk::Dialog::RESPONSE_YES
     end
     dialog.destroy
   end
 
   # Replace the content of the current buffer with the
   # content of a file.
   def open_clicked(widget)
     dialog = Gtk::FileChooserDialog.new(
       "Choose a file ...",
       nil,
       Gtk::FileChooser::ACTION_OPEN,
       nil,
       [ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ],
       [ Gtk::Stock::APPLY, Gtk::Dialog::RESPONSE_APPLY ]
     )
     dialog.run do |response|
       if response == Gtk::Dialog::RESPONSE_APPLY
         file = dialog.filename
         content = IO.readlines(file)
         @texeditor.textview.buffer.text = content.to_s
       end
     end
     dialog.destroy
   end
 
   # Copy the selected text to the clipboard.
   def copy_clicked(widget)
     clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
     @texeditor.textview.buffer.copy_clipboard(clipboard)
   end
 
   # Search for a text string from the current cursor position
   # if there is no selected text, or one character after the
   # cursor if there is.
   def find_clicked(widget)
     find =  @texeditor.search.text
     first, last, success =  @texeditor.textview.buffer.selection_bounds
   
     first =  @texeditor.textview.buffer.start_iter unless success
   
     #                   forward_search(find, flags,    limit=(nil==entire text buffer))
     first, last = first.forward_search(find, Gtk::TextIter::SEARCH_TEXT_ONLY, last)
 
     # Select the instance on the screen if the string is found. 
     # Otherwise, tell the user it has failed.
     if (first)
       mark =  @texeditor.textview.buffer.create_mark(nil, first, false)
       # Scrolls the Gtk::TextView the minimum distance so
       # that mark is contained within the visible area. 
        @texeditor.textview.scroll_mark_onscreen(mark)
 
        @texeditor.textview.buffer.delete_mark(mark)
        @texeditor.textview.buffer.select_range(first, last)
     else
       # Gtk::MessageDialog.new(parent, flags, message_type, button_type, message = nil)
       dialogue = Gtk::MessageDialog.new(
               nil,
               Gtk::Dialog::MODAL,
               Gtk::MessageDialog::INFO, 
               Gtk::MessageDialog::BUTTONS_OK,
               "The text was not found!"
       )
       dialogue.run
       dialogue.destroy
     end
     first = last = nil # camcel any previous selections
   end
   
   # Delete any selected text and insert the clipboard
   # content into the document.
   def paste_clicked(widget)
     clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
     @texeditor.textview.buffer.paste_clipboard(clipboard, nil, true)
   end
   
   # Save the content of the current buffer to a file.
   def save_clicked(widget)
     dialog = Gtk::FileChooserDialog.new(
       "Save the file ...",
       nil,
       Gtk::FileChooser::ACTION_SAVE,
       nil,
       [ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ],
       [ Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_APPLY ]
     )
     dialog.run do |response|
       if response == Gtk::Dialog::RESPONSE_APPLY 
         file = dialog.filename
         content =****@texed*****
         # Open for writing, write and close.
         File.open(file, "w") { |f| f <<  content } 
       end
     end
     dialog.destroy
   end
 
   # Copy the selected text to the clipboard and remove it from the buffer.
   def cut_clicked(widget)
     clipboard = Gtk::Clipboard.get(Gdk::Selection::CLIPBOARD)
     @texeditor.textview.buffer.cut_clipboard(clipboard, true)
   end
 end
 
 # Main program
 if __FILE__ == $0
   # Set values as your own application. 
   PROG_PATH = "ex10-1-editor-tb.glade"
   PROG_NAME = "YOUR_APPLICATION_NAME"
   o = Ex101EditorTbGlade.new(PROG_PATH, nil, PROG_NAME)
   o.glade["window"].show_all
   Gtk.main
 end




ruby-gnome2-cvs メーリングリストの案内
Back to archive index