1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/ext/tk/lib/tk/menuspec.rb
nobu 287a34ae0d * {ext,lib,test}/**/*.rb: removed trailing spaces.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22784 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-03-06 03:56:38 +00:00

275 lines
8.3 KiB
Ruby

#
# tk/menuspec.rb
# Hidethoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
# based on tkmenubar.rb :
# Copyright (C) 1998 maeda shugo. All rights reserved.
# This file can be distributed under the terms of the Ruby.
#
# The format of the menu_spec is:
# [ menu_info, menu_info, ... ]
#
# And the format of the menu_info is:
# [
# [text, underline, configs], # menu button/entry (*1)
# [label, command, underline, accelerator, configs], # command entry
# [label, TkVar_obj, underline, accelerator, configs], # checkbutton entry
# [label, [TkVar_obj, value],
# underline, accelerator, configs], # radiobutton entry
# [label, [[...menu_info...], [...menu_info...], ...],
# underline, accelerator, configs], # cascade entry (*2)
# '---', # separator
# ...
# ]
#
# underline, accelerator, and configs are optional pearameters.
# Hashes are OK instead of Arrays. Then the entry type ('command',
# 'checkbutton', 'radiobutton' or 'cascade') is given by 'type' key
# (e.g. :type=>'cascade'). When type is 'cascade', an array of menu_info
# is acceptable for 'menu' key (then, create sub-menu).
#
# NOTE: (*1)
# If you want to make special menus (*.help for UNIX, *.system for Win,
# and *.apple for Mac), append 'menu_name'=>name (name is 'help' for UNIX,
# 'system' for Win, and 'apple' for Mac) option to the configs hash of
# menu button/entry information.
#
# NOTE: (*2)
# If you want to configure a cascade menu, add :menu_config=>{...configs..}
# to the configs of the cascade entry.
module TkMenuSpec
def _create_menu(parent, menu_info, menu_name = nil,
tearoff = false, default_opts = nil)
if tearoff.kind_of?(Hash)
default_opts = tearoff
tearoff = false
end
if menu_name.kind_of?(Hash)
default_opts = menu_name
menu_name = nil
tearoff = false
end
if default_opts.kind_of?(Hash)
orig_opts = _symbolkey2str(default_opts)
else
orig_opts = {}
end
tearoff = orig_opts.delete('tearoff') if orig_opts.key?('tearoff')
if menu_name
#menu = Tk::Menu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
# --> use current TkMenu class
menu = TkMenu.new(parent, :widgetname=>menu_name, :tearoff=>tearoff)
else
#menu = Tk::Menu.new(parent, :tearoff=>tearoff)
# --> use current TkMenu class
menu = TkMenu.new(parent, :tearoff=>tearoff)
end
for item_info in menu_info
if item_info.kind_of?(Hash)
options = orig_opts.dup
options.update(_symbolkey2str(item_info))
item_type = (options.delete('type') || 'command').to_s
menu_name = options.delete('menu_name')
menu_opts = orig_opts.dup
menu_opts.update(_symbolkey2str(options.delete('menu_config') || {}))
if item_type == 'cascade' && options['menu'].kind_of?(Array)
# create cascade menu
submenu = _create_menu(menu, options['menu'], menu_name,
tearoff, menu_opts)
options['menu'] = submenu
end
menu.add(item_type, options)
elsif item_info.kind_of?(Array)
options = orig_opts.dup
options['label'] = item_info[0] if item_info[0]
case item_info[1]
when TkVariable
# checkbutton
item_type = 'checkbutton'
options['variable'] = item_info[1]
options['onvalue'] = true
options['offvalue'] = false
when Array
# radiobutton or cascade
if item_info[1][0].kind_of?(TkVariable)
# radiobutton
item_type = 'radiobutton'
options['variable'] = item_info[1][0]
options['value'] = item_info[1][1] if item_info[1][1]
else
# cascade
item_type = 'cascade'
menu_opts = orig_opts.dup
if item_info[4] && item_info[4].kind_of?(Hash)
opts = _symbolkey2str(item_info[4])
menu_name = opts.delete('menu_name')
menu_config = opts.delete('menu_config') || {}
menu_opts.update(_symbolkey2str(menu_config))
end
submenu = _create_menu(menu, item_info[1], menu_name,
tearoff, menu_opts)
options['menu'] = submenu
end
else
# command
item_type = 'command'
options['command'] = item_info[1] if item_info[1]
end
options['underline'] = item_info[2] if item_info[2]
options['accelerator'] = item_info[3] if item_info[3]
if item_info[4] && item_info[4].kind_of?(Hash)
opts = _symbolkey2str(item_info[4])
if item_type == 'cascade'
opts.delete('menu_name')
opts.delete('menu_config')
end
options.update(opts)
end
menu.add(item_type, options)
elsif /^-+$/ =~ item_info
menu.add('separator')
else
menu.add('command', 'label' => item_info)
end
end
menu
end
private :_create_menu
def _use_menubar?(parent)
use_menubar = false
if parent.kind_of?(Tk::Root) || parent.kind_of?(Tk::Toplevel)
true
elsif parent.current_configinfo.has_key?('menu')
true
else
false
end
end
private :_use_menubar?
def _create_menu_for_menubar(parent)
#unless (mbar = parent.menu).kind_of?(TkMenu)
# --> use current TkMenu class
mbar = parent.menu
unless mbar.kind_of?(Tk::Menu) || mbar.kind_of?(TkMenu)
#mbar = Tk::Menu.new(parent, :tearoff=>false)
mbar = TkMenu.new(parent, :tearoff=>false)
parent.menu(mbar)
end
mbar
end
private :_create_menu_for_menubar
def _create_menubutton(parent, menu_info, tearoff=false, default_opts = nil)
btn_info = menu_info[0]
if tearoff.kind_of?(Hash)
default_opts = tearoff
tearoff = false
end
if default_opts.kind_of?(Hash)
keys = _symbolkey2str(default_opts)
else
keys = {}
end
tearoff = keys.delete('tearoff') if keys.key?('tearoff')
if _use_menubar?(parent)
# menubar by menu entries
mbar = _create_menu_for_menubar(parent)
menu_name = nil
if btn_info.kind_of?(Hash)
keys.update(_symbolkey2str(btn_info))
menu_name = keys.delete('menu_name')
keys['label'] = keys.delete('text') if keys.key?('text')
elsif btn_info.kind_of?(Array)
keys['label'] = btn_info[0] if btn_info[0]
keys['underline'] = btn_info[1] if btn_info[1]
if btn_info[2]&&btn_info[2].kind_of?(Hash)
keys.update(_symbolkey2str(btn_info[2]))
menu_name = keys.delete('menu_name')
end
else
keys = {:label=>btn_info}
end
menu = _create_menu(mbar, menu_info[1..-1], menu_name,
tearoff, default_opts)
menu.tearoff(tearoff)
keys['menu'] = menu
mbar.add('cascade', keys)
[mbar, menu]
else
# menubar by menubuttons
#mbtn = Tk::Menubutton.new(parent)
# --> use current TkMenubutton class
mbtn = TkMenubutton.new(parent)
menu_name = nil
if btn_info.kind_of?(Hash)
keys.update(_symbolkey2str(btn_info))
menu_name = keys.delete('menu_name')
keys['text'] = keys.delete('label') if keys.key?('label')
mbtn.configure(keys)
elsif btn_info.kind_of?(Array)
mbtn.configure('text', btn_info[0]) if btn_info[0]
mbtn.configure('underline', btn_info[1]) if btn_info[1]
# mbtn.configure('accelerator', btn_info[2]) if btn_info[2]
if btn_info[2]&&btn_info[2].kind_of?(Hash)
keys.update(_symbolkey2str(btn_info[2]))
menu_name = keys.delete('menu_name')
mbtn.configure(keys)
end
else
mbtn.configure('text', btn_info)
end
mbtn.pack('side' => 'left')
menu = _create_menu(mbtn, menu_info[1..-1], menu_name,
tearoff, default_opts)
mbtn.menu(menu)
[mbtn, menu]
end
end
private :_create_menubutton
def _get_cascade_menus(menu)
menus = []
(0..(menu.index('last'))).each{|idx|
if menu.menutype(idx) == 'cascade'
submenu = menu.entrycget(idx, 'menu')
menus << [submenu, _get_cascade_menus(submenu)]
end
}
menus
end
private :_get_cascade_menus
end