# -*- coding: utf-8 -*-
=begin
tiny text editor
=end
require 'gtk2'
#
# Editorのテキスト表示/操作のためのクラス定義
#
class MyEditor
# initialize:インスタンス生成
def initialize(root)
@view = Gtk::TextView.new # テキスト表示領域
@buffer = view.buffer # テキストデータ
@root = root
set_title(nil)
end
# ファイルオープンハンドラ
def open
fname = get_filename('Open file',
Gtk::FileChooser::ACTION_OPEN,
Gtk::Stock::OPEN)
if fname
File.open(fname) do |f|
raw_text = f.read
text = GLib.locale_to_utf8(raw_text)
@buffer.set_text(text)
end
set_title(File.basename(fname))
end
end
# ファイルセーブハンドラ
def save
fname = get_filename('Save file',
Gtk::FileChooser::ACTION_SAVE,
Gtk::Stock::SAVE)
if fname
File.open(fname,'w') do |f|
f.write(@buffer.text)
end
set_title(File.basename(fname))
end
end
# 終了ハンドラ
def quit
Gtk.main_quit
end
# Aboutハンドラ
def about
popup_about_dialog()
end
# メニュー項目データにハンドラを登録
def setup_handlers(action)
action.each do |act|
if has_handler?(act)
handler_name = act.pop # 最後のエントリ
act.push(Proc.new{self.send(handler_name)})
end
end
end
# インスタンス変数@viewを直接外部に公開(読み出し専用)
attr_reader :view
# 以下のメソッドは外部に非公開
private
# "About" message
ABOUT_TEXT = %Q[Tiny Text Editor for "Programming Exercise (Ruby)"\nHIOKI Hirohisa (2015)\n\n You can Open/Edit/Save files.]
PROG_TITLE='ted'
# get filename
def get_filename(title,acttype,stock)
dialog = Gtk::FileChooserDialog.new(title,nil,acttype,
'gnome-vfs',
[stock,Gtk::Dialog::RESPONSE_ACCEPT],
[Gtk::Stock::CANCEL,Gtk::Dialog::RESPONSE_CANCEL])
fname = nil
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
fname = dialog.filename()
end
dialog.destroy
fname
end
# About Dialog
def popup_about_dialog
msg = Gtk::MessageDialog.new(nil,
Gtk::Dialog::MODAL,
Gtk::MessageDialog::INFO,
Gtk::MessageDialog::BUTTONS_OK,
ABOUT_TEXT)
msg.run
msg.destroy
end
def set_title(title)
if title
@root.set_title(PROG_TITLE+"(#{title})")
else
@root.set_title(PROG_TITLE)
end
end
def has_handler?(act)
act.length == 6
end
end
# メニュー構造の定義
UI_INFO = %Q[
]
# メニューの項目定義
ACTIONS = [
# メニュータイトル
# [action名,アイコン,表示されるメニュー名]
['FileMenu',nil,'_File'],
['HelpMenu',nil,'_Help'],
# メニュー項目
# [action名,アイコン,表示される項目名,ショートカット,説明,ハンドラ名]
['Open',Gtk::Stock::OPEN,'_Open','O','Open a file','open'],
['Save',Gtk::Stock::SAVE,'_Save','S','Save to a file','save'],
['Quit',Gtk::Stock::QUIT,'_Quit','Q','Quit this application','quit'],
['About',Gtk::Stock::DIALOG_INFO,'_About',nil,'About this application','about']
]
# ウインドウサイズ
DEFAULT_WIDTH=640
DEFAULT_HEIGHT=480
# トップレベルウインドウ
window = Gtk::Window.new
window.signal_connect('destroy') { Gtk.main_quit }
window.signal_connect('delete_event') { false }
window.set_default_size(DEFAULT_WIDTH,DEFAULT_HEIGHT) # サイズを指定
# エディタ
ed = MyEditor.new(window)
ed.setup_handlers(ACTIONS) # メニューハンドラ登録設定
# メニュー設定
actiongroup = Gtk::ActionGroup.new('Actions')
actiongroup.add_actions(ACTIONS)
uimanager = Gtk::UIManager.new
uimanager.insert_action_group(actiongroup,0)
uimanager.add_ui(UI_INFO)
window.add_accel_group(uimanager.accel_group)
# スクロールバーつきウインドウ
scwin = Gtk::ScrolledWindow.new
# layout
vbox = Gtk::VBox.new
vbox.pack_start(uimanager['/MenuBar'],false,false)
vbox.pack_start(scwin.add(ed.view))
window.add(vbox)
window.show_all # 表示
Gtk.main # イベントループ