mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
307 lines
6.6 KiB
Ruby
307 lines
6.6 KiB
Ruby
|
#!/usr/bin/env ruby
|
||
|
#
|
||
|
# This script implements the "hv" application. Type "hv FILE" to
|
||
|
# view FILE as HTML.
|
||
|
#
|
||
|
# This application is used for testing the HTML widget. It can
|
||
|
# also server as an example of how to use the HTML widget.
|
||
|
#
|
||
|
require 'tk'
|
||
|
require 'tkextlib/tkHTML'
|
||
|
|
||
|
root = TkRoot.new(:title=>'HTML File Viewer', :iconname=>'HV')
|
||
|
|
||
|
file = ARGV[0]
|
||
|
|
||
|
#
|
||
|
# These images are used in place of GIFs or of form elements
|
||
|
#
|
||
|
biggray = TkPhotoImage.new(:data=><<'EOD')
|
||
|
R0lGODdhPAA+APAAALi4uAAAACwAAAAAPAA+AAACQISPqcvtD6OctNqLs968+w+G4kiW5omm
|
||
|
6sq27gvH8kzX9o3n+s73/g8MCofEovGITCqXzKbzCY1Kp9Sq9YrNFgsAO///
|
||
|
EOD
|
||
|
|
||
|
smgray = TkPhotoImage.new(:data=><<'EOD')
|
||
|
R0lGODdhOAAYAPAAALi4uAAAACwAAAAAOAAYAAACI4SPqcvtD6OctNqLs968+w+G4kiW5omm
|
||
|
6sq27gvH8kzX9m0VADv/
|
||
|
EOD
|
||
|
|
||
|
nogifbig = TkPhotoImage.new(:data=><<'EOD')
|
||
|
R0lGODdhJAAkAPEAAACQkADQ0PgAAAAAACwAAAAAJAAkAAACmISPqcsQD6OcdJqKM71PeK15
|
||
|
AsSJH0iZY1CqqKSurfsGsex08XuTuU7L9HywHWZILAaVJssvgoREk5PolFo1XrHZ29IZ8oo0
|
||
|
HKEYVDYbyc/jFhz2otvdcyZdF68qeKh2DZd3AtS0QWcDSDgWKJXY+MXS9qY4+JA2+Vho+YPp
|
||
|
FzSjiTIEWslDQ1rDhPOY2sXVOgeb2kBbu1AAADv/
|
||
|
EOD
|
||
|
|
||
|
nogifsm = TkPhotoImage.new(:data=><<'EOD')
|
||
|
R0lGODdhEAAQAPEAAACQkADQ0PgAAAAAACwAAAAAEAAQAAACNISPacHtD4IQz80QJ60as25d
|
||
|
3idKZdR0IIOm2ta0Lhw/Lz2S1JqvK8ozbTKlEIVYceWSjwIAO///
|
||
|
EOD
|
||
|
|
||
|
#
|
||
|
# define variables
|
||
|
#
|
||
|
ul_hyper = TkVariable.new(0)
|
||
|
show_tbl = TkVariable.new(0)
|
||
|
show_img = TkVariable.new(1)
|
||
|
|
||
|
#
|
||
|
# A font chooser routine.
|
||
|
#
|
||
|
# html[:fontcommand] = pick_font
|
||
|
pick_font = proc{|size, attrs|
|
||
|
puts "FontCmd: #{size} #{attrs}"
|
||
|
[ ((attrs =~ /fixed/)? 'courier': 'charter'),
|
||
|
(12 * (1.2**(size.to_f - 4.0))).to_i,
|
||
|
((attrs =~ /italic/)? 'italic': 'roman'),
|
||
|
((attrs =~ /bold/)? 'bold': 'normal') ].join(' ')
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# This routine is called for each form element
|
||
|
#
|
||
|
form_cmd = proc{|n, cmd, style, *args|
|
||
|
# puts "FormCmd: $n $cmd $args"
|
||
|
case cmd
|
||
|
when 'select', 'textarea', 'input'
|
||
|
TkLabel.new(:widgetname=>args[0], :image=>nogifsm)
|
||
|
end
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# This routine is called for every <IMG> markup
|
||
|
#
|
||
|
images = {}
|
||
|
old_imgs = {}
|
||
|
big_imgs = {}
|
||
|
|
||
|
hotkey = {}
|
||
|
|
||
|
move_big_image = proc{|b|
|
||
|
return unless big_imgs.key?(b)
|
||
|
b.copy(big_imgs[b])
|
||
|
big_imgs[b].delete
|
||
|
big_imgs.delete(b)
|
||
|
Tk.update
|
||
|
}
|
||
|
|
||
|
image_cmd = proc{|*args|
|
||
|
return smgray unless show_img.bool
|
||
|
fn = args[0]
|
||
|
if old_imgs.key?(fn)
|
||
|
images[fn] = old_imgs[fn]
|
||
|
old_imgs.delete(fn)
|
||
|
return images[fn]
|
||
|
end
|
||
|
|
||
|
begin
|
||
|
img = TkPhotoImage.new(:file=>fn)
|
||
|
rescue
|
||
|
return smgray
|
||
|
end
|
||
|
|
||
|
if img.width * img.height > 20000
|
||
|
b = TkPhotoImage.new(:width=>img.width, :height=>img.height)
|
||
|
big_imgs[b] = img
|
||
|
img = b
|
||
|
Tk.after_idle(proc{ move_big_image.call(b) })
|
||
|
end
|
||
|
|
||
|
images[fn] = img
|
||
|
|
||
|
img
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# This routine is called for every <SCRIPT> markup
|
||
|
#
|
||
|
script_cmd = proc{|*args|
|
||
|
# puts "ScriptCmd: #{args.inspect}"
|
||
|
}
|
||
|
|
||
|
# This routine is called for every <APPLET> markup
|
||
|
#
|
||
|
applet_cmd = proc{|w, arglist|
|
||
|
# puts "AppletCmd: w=#{w} arglist=#{arglist}"
|
||
|
TkLabel.new(w, :text=>"The Applet #{w}", :bd=>2, :relief=>raised)
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Construct the main HTML viewer
|
||
|
#
|
||
|
html = Tk::HTML_Widget.new(:padx=>5, :pady=>9,
|
||
|
:formcommand=>form_cmd,
|
||
|
:imagecommand=>image_cmd,
|
||
|
:scriptcommand=>script_cmd,
|
||
|
:appletcommand=>applet_cmd,
|
||
|
:underlinehyperlinks=>0,
|
||
|
:bg=>'white', :tablerelief=>:raised)
|
||
|
vscr = html.yscrollbar(TkScrollbar.new)
|
||
|
hscr = html.xscrollbar(TkScrollbar.new)
|
||
|
|
||
|
Tk.grid(html, vscr, :sticky=>:news)
|
||
|
Tk.grid(hscr, :sticky=>:ew)
|
||
|
Tk.root.grid_columnconfigure(0, :weight=>1)
|
||
|
Tk.root.grid_columnconfigure(1, :weight=>0)
|
||
|
Tk.root.grid_rowconfigure(0, :weight=>1)
|
||
|
Tk.root.grid_rowconfigure(1, :weight=>0)
|
||
|
|
||
|
#
|
||
|
# This procedure is called when the user clicks on a hyperlink.
|
||
|
#
|
||
|
priv = {}
|
||
|
last_file = ''
|
||
|
|
||
|
# Read a file
|
||
|
#
|
||
|
read_file = proc{|name|
|
||
|
begin
|
||
|
fp = open(name, 'r')
|
||
|
ret = fp.read(File.size(name))
|
||
|
rescue
|
||
|
ret = nil
|
||
|
fp = nil
|
||
|
Tk.messageBox(:icon=>'error', :message=>"fail to open '#{name}'",
|
||
|
:type=>:ok)
|
||
|
ensure
|
||
|
fp.close if fp
|
||
|
end
|
||
|
ret
|
||
|
}
|
||
|
|
||
|
# Clear the screen.
|
||
|
#
|
||
|
clear_screen = proc{
|
||
|
html.clear
|
||
|
old_imgs.clear
|
||
|
big_imgs.clear
|
||
|
hotkey.clear
|
||
|
images.each{|k, v| old_imgs[k] = v }
|
||
|
images.clear
|
||
|
}
|
||
|
|
||
|
# Load a file into the HTML widget
|
||
|
#
|
||
|
load_file = proc{|name|
|
||
|
return unless (doc = read_file.call(name))
|
||
|
clear_screen.call
|
||
|
last_file = name
|
||
|
html.configure(:base=>name)
|
||
|
html.parse(doc)
|
||
|
old_imgs.clear
|
||
|
}
|
||
|
|
||
|
href_binding = proc{|x, y|
|
||
|
# koba & dg marking text
|
||
|
html.selection_clear
|
||
|
priv['mark'] = "@#{x},#{y}"
|
||
|
lst = html.href(x, y)
|
||
|
return if lst.size.zero?
|
||
|
|
||
|
lnk, target = lst
|
||
|
|
||
|
if lnk != ""
|
||
|
if lnk =~ /^#{last_file}#(.*)$/
|
||
|
html.yview($1)
|
||
|
else
|
||
|
load_file.call(lnk)
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
html.clipping_window.bind('1', href_binding, '%x %y')
|
||
|
|
||
|
# marking text with the mouse and copying to the clipboard just with tkhtml2.0 working
|
||
|
html.clipping_window.bind('B1-Motion', proc{|w, x, y|
|
||
|
w.selection_set(priv['mark'], "@#{x},#{y}")
|
||
|
TkClipboard.clear
|
||
|
# avoid tkhtml0.0 errors
|
||
|
# anyone can fix this for tkhtml0.0
|
||
|
begin
|
||
|
TkClipboard.append(TkSelection.get)
|
||
|
rescue
|
||
|
end
|
||
|
}, '%W %x %y')
|
||
|
|
||
|
# This procedure is called when the user selects the File/Open
|
||
|
# menu option.
|
||
|
#
|
||
|
last_dir = Dir.pwd
|
||
|
sel_load = proc{
|
||
|
filetypes = [
|
||
|
['Html Files', ['.html', '.htm']],
|
||
|
['All Files', '*']
|
||
|
]
|
||
|
|
||
|
f = Tk.getOpenFile(:initialdir=>last_dir, :filetypes=>filetypes)
|
||
|
if f != ''
|
||
|
load_file.call(f)
|
||
|
last_dir = File.dirname(f)
|
||
|
end
|
||
|
}
|
||
|
|
||
|
# Refresh the current file.
|
||
|
#
|
||
|
refresh = proc{|*args|
|
||
|
load_file.call(last_file)
|
||
|
}
|
||
|
|
||
|
# This binding changes the cursor when the mouse move over
|
||
|
# top of a hyperlink.
|
||
|
#
|
||
|
Tk::HTML_Widget::ClippingWindow.bind('Motion', proc{|w, x, y|
|
||
|
parent = w.winfo_parent
|
||
|
url = parent.href(x, y)
|
||
|
unless url.empty?
|
||
|
parent[:cursor] = 'hand2'
|
||
|
else
|
||
|
parent[:cursor] = ''
|
||
|
end
|
||
|
}, '%W %x %y')
|
||
|
#
|
||
|
# Setup menu
|
||
|
#
|
||
|
menu_spec = [
|
||
|
[['File', 0],
|
||
|
['Open', sel_load, 0],
|
||
|
['Refresh', refresh, 0],
|
||
|
'---',
|
||
|
['Exit', proc{exit}, 1]],
|
||
|
|
||
|
[['View', 0],
|
||
|
['Underline Hyperlinks', ul_hyper],
|
||
|
['Show Table Structure', show_tbl],
|
||
|
['Show Images', show_img]]
|
||
|
]
|
||
|
|
||
|
mbar = Tk.root.add_menubar(menu_spec)
|
||
|
|
||
|
#
|
||
|
# Setup trace
|
||
|
#
|
||
|
ul_hyper.trace('w', proc{
|
||
|
html[:underlinehyperlinks] = ul_hyper.value
|
||
|
refresh.call
|
||
|
})
|
||
|
|
||
|
show_tbl.trace('w', proc{
|
||
|
if show_tbl.bool
|
||
|
html[:tablerelief] = :flat
|
||
|
else
|
||
|
html[:tablerelief] = :raised
|
||
|
end
|
||
|
refresh.call
|
||
|
})
|
||
|
|
||
|
show_img.trace('w', refresh)
|
||
|
|
||
|
# If an arguent was specified, read it into the HTML widget.
|
||
|
#
|
||
|
Tk.update
|
||
|
if file && file != ""
|
||
|
load_file.call(file)
|
||
|
end
|
||
|
|
||
|
#####################################
|
||
|
|
||
|
Tk.mainloop
|