mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* ext/tk/sample/tkmulticolumnlist.rb: new sample
* ext/tk/sample/tkmultilistframe.rb: bug fix git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5281 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									42da260543
								
							
						
					
					
						commit
						8855456929
					
				
					 4 changed files with 761 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -1,3 +1,9 @@
 | 
			
		|||
Wed Dec 24 20:53:06 2003  Hidetoshi NAGAI  <nagai@ai.kyutech.ac.jp>
 | 
			
		||||
 | 
			
		||||
	* ext/tk/sample/tkmulticolumnlist.rb: new sample
 | 
			
		||||
 | 
			
		||||
	* ext/tk/sample/tkmultilistframe.rb: bug fix
 | 
			
		||||
 | 
			
		||||
Wed Dec 24 20:37:37 2003  Eric Sunshine  <sunshine@sunshineco.com>
 | 
			
		||||
 | 
			
		||||
	* configure.in (LDSHARED): Fixed typographical error in assignment of
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,7 @@ sample/tkfrom.rb
 | 
			
		|||
sample/tkhello.rb
 | 
			
		||||
sample/tkline.rb
 | 
			
		||||
sample/tkmenubutton.rb
 | 
			
		||||
sample/tkmulticolumnlist.rb
 | 
			
		||||
sample/tkmultilistbox.rb
 | 
			
		||||
sample/tkmultilistframe.rb
 | 
			
		||||
sample/tkoptdb-safeTk.rb
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										743
									
								
								ext/tk/sample/tkmulticolumnlist.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										743
									
								
								ext/tk/sample/tkmulticolumnlist.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,743 @@
 | 
			
		|||
#
 | 
			
		||||
# tkmulticolumnlist.rb : multiple column list widget on scrollable frame
 | 
			
		||||
#                        by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
 | 
			
		||||
#
 | 
			
		||||
require 'tk'
 | 
			
		||||
 | 
			
		||||
class TkMultiColumnList < TkText
 | 
			
		||||
  include TkComposite
 | 
			
		||||
 | 
			
		||||
  #   lbox_height : height of listboxes (pixel)
 | 
			
		||||
  #   title_info  : array [ [<title_string>,<init_width>], ... ]
 | 
			
		||||
  #   keys        : hash {<option>=><value>, ... }
 | 
			
		||||
  def initialize_composite(lbox_height, title_info, keys={})
 | 
			
		||||
    # argument check
 | 
			
		||||
    if (! title_info.kind_of? Array) or (title_info.size < 2)
 | 
			
		||||
      raise
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # mode
 | 
			
		||||
    @keep_minsize = true
 | 
			
		||||
    @show_each_hscr = true
 | 
			
		||||
    @show_win_hscr = true
 | 
			
		||||
 | 
			
		||||
    # init arrays
 | 
			
		||||
    @base_list  = []
 | 
			
		||||
    @rel_list   = []
 | 
			
		||||
    @title_list = []
 | 
			
		||||
    @title_cmd  = []
 | 
			
		||||
    @lbox_list  = []
 | 
			
		||||
    @hscr_list  = []
 | 
			
		||||
 | 
			
		||||
    # decide total width
 | 
			
		||||
    @lbox_total = title_info.size
 | 
			
		||||
    @width_total = 0
 | 
			
		||||
    title_info.each{|title, width, cmd| 
 | 
			
		||||
      @width_total += width.to_f
 | 
			
		||||
      @title_cmd << cmd
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # rel-table of label=>index
 | 
			
		||||
    @name_index = {}
 | 
			
		||||
 | 
			
		||||
    # size definition
 | 
			
		||||
    @window_width = @width_total
 | 
			
		||||
    @sash = 5
 | 
			
		||||
    @scrbar_width = 15
 | 
			
		||||
    @scrbar_border = 3
 | 
			
		||||
    @lbox_border = 1
 | 
			
		||||
    @title_border = 3
 | 
			
		||||
    @h_l_thick = 0
 | 
			
		||||
 | 
			
		||||
    # init status
 | 
			
		||||
    @mode = :title
 | 
			
		||||
    @command = nil
 | 
			
		||||
 | 
			
		||||
    # virtical scrollbar
 | 
			
		||||
    @v_scroll = TkYScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
				 'borderwidth'=>@scrbar_border, 
 | 
			
		||||
				 'width'=>@scrbar_width)
 | 
			
		||||
 | 
			
		||||
    # horizontal scrollbar
 | 
			
		||||
    @h_scroll = TkXScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
				 'borderwidth'=>@scrbar_border, 
 | 
			
		||||
				 'width'=>@scrbar_width)
 | 
			
		||||
 | 
			
		||||
    # create base flames
 | 
			
		||||
    @c_title = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
			    'width'=>@window_width)
 | 
			
		||||
    @f_title = TkFrame.new(@c_title, 'width'=>@width_total)
 | 
			
		||||
    @w_title = TkcWindow.new(@c_title, 0, 0, 
 | 
			
		||||
			     'window'=>@f_title, 'anchor'=>'nw')
 | 
			
		||||
 | 
			
		||||
    @c_lbox  = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
			    'width'=>@window_width)
 | 
			
		||||
    @f_lbox  = TkFrame.new(@c_lbox, 'width'=>@width_total)
 | 
			
		||||
    @w_lbox  = TkcWindow.new(@c_lbox, 0, 0, 'window'=>@f_lbox, 'anchor'=>'nw')
 | 
			
		||||
 | 
			
		||||
    @c_hscr  = TkCanvas.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
			    'width'=>@window_width)
 | 
			
		||||
    @f_hscr  = TkFrame.new(@c_hscr, 'width'=>@width_total)
 | 
			
		||||
    @w_hscr  = TkcWindow.new(@c_hscr, 0, 0, 'window'=>@f_hscr, 'anchor'=>'nw')
 | 
			
		||||
 | 
			
		||||
    # create each listbox
 | 
			
		||||
    sum = 0.0
 | 
			
		||||
    @rel_list << sum/@width_total
 | 
			
		||||
    title_info.each_with_index{|(label, width), idx|
 | 
			
		||||
      # set relation between label and index
 | 
			
		||||
      if @name_index.include?(label)
 | 
			
		||||
	@name_index[label] << idx
 | 
			
		||||
      else
 | 
			
		||||
	@name_index[label] = [idx]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # calculate relative positioning
 | 
			
		||||
      sum += width
 | 
			
		||||
      @rel_list << sum/@width_total
 | 
			
		||||
 | 
			
		||||
      # title field
 | 
			
		||||
      f = TkFrame.new(@f_title, 'width'=>width)
 | 
			
		||||
      base = [f]
 | 
			
		||||
 | 
			
		||||
      title = TkLabel.new(f, 'text'=>label, 'borderwidth'=>@title_border, 
 | 
			
		||||
			  'relief'=>'raised', 'highlightthickness'=>@h_l_thick)
 | 
			
		||||
      title_binding(title, idx)
 | 
			
		||||
      title.pack('fill'=>'x')
 | 
			
		||||
 | 
			
		||||
      @title_list << title
 | 
			
		||||
 | 
			
		||||
      f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1, 
 | 
			
		||||
	      'relheight'=>1.0, 
 | 
			
		||||
	      'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
 | 
			
		||||
 | 
			
		||||
      # listbox field
 | 
			
		||||
      f = TkFrame.new(@f_lbox, 'width'=>width)
 | 
			
		||||
      base << f
 | 
			
		||||
      @lbox_list << TkText.new(f, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
			       'borderwidth'=>@lbox_border, 
 | 
			
		||||
			       'takefocus'=>false, 
 | 
			
		||||
			       'wrap'=>'none') {
 | 
			
		||||
 | 
			
		||||
	bindtags(bindtags - [TkText])
 | 
			
		||||
 | 
			
		||||
	@seltag = TkTextTag.new(self, 'background'=>'#b3b3b3', 
 | 
			
		||||
				'borderwidth'=>1, 'relief'=>'raised')
 | 
			
		||||
	def self.nearest(y)
 | 
			
		||||
	  self.index("@1,#{y}").split('.')[0].to_i
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	def self.select_clear(first, last=nil)
 | 
			
		||||
	  first = "#{first}.0" if first.kind_of?(Integer)
 | 
			
		||||
	  first = self.index(first.to_s + ' linestart')
 | 
			
		||||
	  last = first unless last
 | 
			
		||||
	  last = "#{last}.0" if first.kind_of?(Integer)
 | 
			
		||||
	  last = self.index(last.to_s + ' + 1 lines linestart')
 | 
			
		||||
	  @seltag.remove(first, last)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	def self.select_set(first, last=nil)
 | 
			
		||||
	  first = "#{first}.0" if first.kind_of?(Integer)
 | 
			
		||||
	  first = self.index(first.to_s + ' linestart')
 | 
			
		||||
	  last = first unless last
 | 
			
		||||
	  last = "#{last}.0" if first.kind_of?(Integer)
 | 
			
		||||
	  last = self.index(last.to_s + ' + 1 lines linestart')
 | 
			
		||||
	  @seltag.add(first, last)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	def self.select_index
 | 
			
		||||
	  self.index(@seltag.first).split('.')[0].to_i
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	pack('fill'=>'both', 'expand'=>true)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1, 
 | 
			
		||||
	      'relwidth'=>@rel_list[idx+1] - @rel_list[idx], 'relheight'=>1.0)
 | 
			
		||||
 | 
			
		||||
      # scrollbar field
 | 
			
		||||
      f = TkFrame.new(@f_hscr, 'width'=>width)
 | 
			
		||||
      base << f
 | 
			
		||||
      @hscr_list << TkXScrollbar.new(f, 'width'=>@scrbar_width, 
 | 
			
		||||
				     'borderwidth'=>@scrbar_border, 
 | 
			
		||||
				     'highlightthickness'=>@h_l_thick
 | 
			
		||||
				    ).pack('fill'=>'x', 'anchor'=>'w')
 | 
			
		||||
      f.place('relx'=>@rel_list[idx], 'y'=>0, 'anchor'=>'nw', 'width'=>1, 
 | 
			
		||||
	      'relwidth'=>@rel_list[idx+1] - @rel_list[idx])
 | 
			
		||||
 | 
			
		||||
      @lbox_list[idx].xscrollbar(@hscr_list[idx])
 | 
			
		||||
 | 
			
		||||
      # add new base
 | 
			
		||||
      @base_list << base
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # pad
 | 
			
		||||
    @f_title_pad = TkFrame.new(@frame, 'relief'=>'raised', 
 | 
			
		||||
			       'borderwidth'=>@title_border, 
 | 
			
		||||
			       'highlightthickness'=>@h_l_thick)
 | 
			
		||||
 | 
			
		||||
    @f_scr_pad = TkFrame.new(@frame, 'relief'=>'sunken', 
 | 
			
		||||
			     'borderwidth'=>1, 
 | 
			
		||||
			     'highlightthickness'=>@h_l_thick)
 | 
			
		||||
 | 
			
		||||
    # height check
 | 
			
		||||
    title_height = 0
 | 
			
		||||
    @title_list.each{|w| 
 | 
			
		||||
      h = w.winfo_reqheight
 | 
			
		||||
      title_height = h if title_height < h
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hscr_height = 0
 | 
			
		||||
    @hscr_list.each{|w| 
 | 
			
		||||
      h = w.winfo_reqheight
 | 
			
		||||
      hscr_height = h if hscr_height < h
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @f_title.height title_height
 | 
			
		||||
    @f_lbox.height lbox_height
 | 
			
		||||
    @f_hscr.height hscr_height
 | 
			
		||||
 | 
			
		||||
    # set control procedure for virtical scroll
 | 
			
		||||
    @v_scroll.assign(*@lbox_list)
 | 
			
		||||
 | 
			
		||||
    # set control procedure for horizoncal scroll
 | 
			
		||||
    @h_scroll.assign(@c_title, @c_lbox, @c_hscr)
 | 
			
		||||
 | 
			
		||||
    # binding for listboxes
 | 
			
		||||
    @lbox_list.each_with_index{|l, idx| 
 | 
			
		||||
      l.bind('Button-1', proc{|w, y| 
 | 
			
		||||
	       @frame.focus
 | 
			
		||||
	       select_line(w, w.nearest(y))
 | 
			
		||||
	     }, '%W %y')
 | 
			
		||||
      l.bind('B1-Motion', proc{|w, y| 
 | 
			
		||||
	       select_line(w, w.nearest(y))
 | 
			
		||||
	     }, '%W %y')
 | 
			
		||||
      l.bind('Double-Button-1', proc{
 | 
			
		||||
	       @command.call(get_select) if @command
 | 
			
		||||
	     })
 | 
			
		||||
 | 
			
		||||
      l.bind('Control-Home', proc{|w| select_line(w, 0)}, '%W')
 | 
			
		||||
      l.bind('Control-End', proc{|w| select_line(w, 'end')}, '%W')
 | 
			
		||||
 | 
			
		||||
      l.bind('Button-2', proc{|x, y| 
 | 
			
		||||
	       @lbox_mark_x = x
 | 
			
		||||
	       @lbox_list.each{|lbox| lbox.scan_mark(x, y)}
 | 
			
		||||
	     }, '%x %y')
 | 
			
		||||
      l.bind('B2-Motion', proc{|x, y| 
 | 
			
		||||
	       @lbox_list.each{|lbox| lbox.scan_dragto(@lbox_mark_x, y)}
 | 
			
		||||
	       l.scan_dragto(x, y)
 | 
			
		||||
	     }, '%x %y')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bbox = @w_title.bbox
 | 
			
		||||
    @c_title.height(bbox[3])
 | 
			
		||||
    @c_title.scrollregion(bbox)
 | 
			
		||||
 | 
			
		||||
    bbox = @w_lbox.bbox
 | 
			
		||||
    @c_lbox.height(bbox[3])
 | 
			
		||||
    @c_lbox.scrollregion(bbox)
 | 
			
		||||
 | 
			
		||||
    if @show_each_hscr
 | 
			
		||||
      bbox = @w_hscr.bbox
 | 
			
		||||
      @c_hscr.height(bbox[3])
 | 
			
		||||
      @c_hscr.scrollregion(bbox)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # binding
 | 
			
		||||
    @frame.takefocus(true)
 | 
			
		||||
    @frame.bind('Key-Up', proc{select_shift(@lbox_list[0], -1)})
 | 
			
		||||
    @frame.bind('Key-Down', proc{select_shift(@lbox_list[0], 1)})
 | 
			
		||||
    @frame.bind('Return', proc{@command.call(get_select) if @command})
 | 
			
		||||
 | 
			
		||||
    # alignment
 | 
			
		||||
    TkGrid.rowconfigure(@frame, 0, 'weight'=>0)
 | 
			
		||||
    TkGrid.rowconfigure(@frame, 1, 'weight'=>1)
 | 
			
		||||
    TkGrid.rowconfigure(@frame, 2, 'weight'=>0)
 | 
			
		||||
    TkGrid.rowconfigure(@frame, 3, 'weight'=>0)
 | 
			
		||||
    TkGrid.columnconfigure(@frame, 0, 'weight'=>1)
 | 
			
		||||
    TkGrid.columnconfigure(@frame, 1, 'weight'=>0)
 | 
			
		||||
    TkGrid.columnconfigure(@frame, 2, 'weight'=>0)
 | 
			
		||||
    @v_scroll.grid('row'=>1, 'column'=>2, 'sticky'=>'ns')
 | 
			
		||||
    @c_title.grid('row'=>0, 'column'=>0, 'sticky'=>'news')
 | 
			
		||||
    @f_title_pad.grid('row'=>0, 'column'=>2, 'sticky'=>'news')
 | 
			
		||||
    @c_lbox.grid('row'=>1, 'column'=>0, 'sticky'=>'news')
 | 
			
		||||
    @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew') if @show_each_hscr
 | 
			
		||||
    @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew') if @show_win_hscr
 | 
			
		||||
    @f_scr_pad.grid('row'=>2, 'rowspan'=>2, 'column'=>2, 'sticky'=>'news')
 | 
			
		||||
 | 
			
		||||
    # binding for 'Configure' event
 | 
			
		||||
    @c_lbox.bind('Configure', 
 | 
			
		||||
		 proc{|height, width| reconstruct(height, width)}, 
 | 
			
		||||
		 '%h %w')
 | 
			
		||||
 | 
			
		||||
    # set default receiver of method calls
 | 
			
		||||
    @path = @frame.path
 | 
			
		||||
 | 
			
		||||
    # configure options
 | 
			
		||||
    keys = {} unless keys
 | 
			
		||||
    keys = _symbolkey2str(keys)
 | 
			
		||||
 | 
			
		||||
    # command
 | 
			
		||||
    cmd = keys.delete('command')
 | 
			
		||||
    command(cmd) if cmd
 | 
			
		||||
 | 
			
		||||
    # 'scrollbarwidth' option == 'width' option of scrollbars
 | 
			
		||||
    width = keys.delete('scrollbarwidth')
 | 
			
		||||
    scrollbarwidth(width) if width
 | 
			
		||||
 | 
			
		||||
    # options for listbox titles
 | 
			
		||||
    title_font = keys.delete('titlefont')
 | 
			
		||||
    titlefont(title_font) if title_font
 | 
			
		||||
 | 
			
		||||
    title_fg = keys.delete('titleforeground')
 | 
			
		||||
    titleforeground(title_fg) if title_fg
 | 
			
		||||
 | 
			
		||||
    title_bg = keys.delete('titlebackground')
 | 
			
		||||
    titlebackground(title_bg) if title_bg
 | 
			
		||||
 | 
			
		||||
    # set receivers for configure methods
 | 
			
		||||
    delegate('DEFAULT', *@lbox_list)
 | 
			
		||||
    delegate('activebackground', @v_scroll, @h_scroll, *@hscr_list)
 | 
			
		||||
    delegate('troughcolor', @v_scroll, @h_scroll, *@hscr_list)
 | 
			
		||||
    delegate('repeatdelay', @v_scroll, @h_scroll, *@hscr_list)
 | 
			
		||||
    delegate('repeatinterval', @v_scroll, @h_scroll, *@hscr_list)
 | 
			
		||||
    delegate('borderwidth', @frame)
 | 
			
		||||
    delegate('width', @c_lbox, @c_title, @c_hscr)
 | 
			
		||||
    delegate('relief', @frame)
 | 
			
		||||
 | 
			
		||||
    # configure
 | 
			
		||||
    configure(keys) if keys.size > 0
 | 
			
		||||
  end
 | 
			
		||||
  private :initialize_composite
 | 
			
		||||
 | 
			
		||||
  # keep_minsize?
 | 
			
		||||
  def keep_minsize?
 | 
			
		||||
    @keep_minsize
 | 
			
		||||
  end
 | 
			
		||||
  def keep_minsize(bool)
 | 
			
		||||
    @keep_minsize = bool
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # each hscr
 | 
			
		||||
  def show_each_hscr
 | 
			
		||||
    @show_each_hscr = true
 | 
			
		||||
    @c_hscr.grid('row'=>2, 'column'=>0, 'sticky'=>'ew')
 | 
			
		||||
  end
 | 
			
		||||
  def hide_each_hscr
 | 
			
		||||
    @show_each_hscr = false
 | 
			
		||||
    @c_hscr.ungrid
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # window hscroll
 | 
			
		||||
  def show_win_hscr
 | 
			
		||||
    @show_win_hscr = true
 | 
			
		||||
    @h_scroll.grid('row'=>3, 'column'=>0, 'sticky'=>'ew')
 | 
			
		||||
  end
 | 
			
		||||
  def hide_win_hscr
 | 
			
		||||
    @show_each_hscr = false
 | 
			
		||||
    @h_scroll.ungrid
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set command
 | 
			
		||||
  def command(cmd)
 | 
			
		||||
    @command = cmd
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set scrollbar width
 | 
			
		||||
  def scrollbarwidth(width)
 | 
			
		||||
    @scrbar_width = width
 | 
			
		||||
    @v_scroll['width'] = @scrbar_width
 | 
			
		||||
    @h_scroll['width'] = @scrbar_width
 | 
			
		||||
    @hscr_list.each{|hscr| hscr['width'] = @scrbar_width}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set scrollbar border
 | 
			
		||||
  def scrollbarborder(width)
 | 
			
		||||
    @scrbar_border = width
 | 
			
		||||
    @v_scroll['border'] = @scrbar_border
 | 
			
		||||
    @h_scroll['border'] = @scrbar_border
 | 
			
		||||
    @hscr_list.each{|hscr| hscr['border'] = @scrbar_border}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set listbox borders
 | 
			
		||||
  def listboxborder(width)
 | 
			
		||||
    @lbox_border = width
 | 
			
		||||
    @lbox_list.each{|w| w['border'] = @lbox_border}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set listbox relief
 | 
			
		||||
  def listboxrelief(relief)
 | 
			
		||||
    @lbox_list.each{|w| w['relief'] = relief}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set title borders
 | 
			
		||||
  def titleborder(width)
 | 
			
		||||
    @title_border = width
 | 
			
		||||
    @f_title_pad['border'] = @title_border
 | 
			
		||||
    @title_list.each{|label| label['border'] = @title_border}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set title font
 | 
			
		||||
  def titlefont(font)
 | 
			
		||||
    @title_list.each{|label| label['font'] = font}
 | 
			
		||||
    title_height = 0
 | 
			
		||||
    @title_list.each{|w| 
 | 
			
		||||
      h = w.winfo_reqheight
 | 
			
		||||
      title_height = h if title_height < h
 | 
			
		||||
    }
 | 
			
		||||
    @f_title.height title_height
 | 
			
		||||
    bbox = @w_title.bbox
 | 
			
		||||
    @c_title.height(bbox[3])
 | 
			
		||||
    @c_title.scrollregion(bbox)
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set title foreground color
 | 
			
		||||
  def titleforeground(fg)
 | 
			
		||||
    @title_list.each{|label| label['foreground'] = fg}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set title background color
 | 
			
		||||
  def titlebackground(bg)
 | 
			
		||||
    @f_title_pad['background'] = bg
 | 
			
		||||
    @title_list.each{|label| label['background'] = bg}
 | 
			
		||||
    self
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # set title cmds
 | 
			
		||||
  def titlecommand(idx, cmd=Proc.new)
 | 
			
		||||
    @title_cmd[idx] = cmd
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # call title cmds
 | 
			
		||||
  def titleinvoke(idx)
 | 
			
		||||
    @title_cmd[idx].call if @title_cmd[idx]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # get label widgets of listbox titles
 | 
			
		||||
  def titlelabels(*indices)
 | 
			
		||||
    @title_list[*indices]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # get listbox widgets
 | 
			
		||||
  def columns(*indices)
 | 
			
		||||
    @lbox_list[*indices]
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def delete(*idx)
 | 
			
		||||
    idx = idx.collect{|i|
 | 
			
		||||
      if i.kind_of?(Integer)
 | 
			
		||||
	"#{i}.0"
 | 
			
		||||
      else
 | 
			
		||||
	i.to_s
 | 
			
		||||
      end
 | 
			
		||||
    }
 | 
			
		||||
    @lbox_list.collect{|lbox| lbox.delete(*idx)}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get(idx_s, idx_e=nil)
 | 
			
		||||
    unless idx_e
 | 
			
		||||
      if idx_s.kind_of?(Integer)
 | 
			
		||||
	idx_s = "#{idx_s}.0"
 | 
			
		||||
	idx_e = "#{idx_s} lineend"
 | 
			
		||||
      else
 | 
			
		||||
	idx_s = idx_s.to_s
 | 
			
		||||
	idx_e = "#{idx_s} lineend"
 | 
			
		||||
      end
 | 
			
		||||
      @lbox_list.collect{|lbox|
 | 
			
		||||
	lbox.get(idx_s, idx_e)
 | 
			
		||||
      }
 | 
			
		||||
    else
 | 
			
		||||
      if idx_s.kind_of?(Integer)
 | 
			
		||||
	idx_s = "#{idx_s}.0"
 | 
			
		||||
      else
 | 
			
		||||
	idx_s = idx_s.to_s
 | 
			
		||||
      end
 | 
			
		||||
      if idx_e.kind_of?(Integer)
 | 
			
		||||
	idx_e = "#{idx_e}.end"
 | 
			
		||||
      else
 | 
			
		||||
	idx_e = "#{idx_e} lineend"
 | 
			
		||||
      end
 | 
			
		||||
      list = @lbox_list.collect{|lbox| lbox.get(idx_s, idx_e).split(/\n/)}
 | 
			
		||||
      result = []
 | 
			
		||||
      list[0].each_with_index{|line, index|
 | 
			
		||||
	result << list.collect{|lines| lines[index]}
 | 
			
		||||
      }
 | 
			
		||||
      result
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def get_select
 | 
			
		||||
    get(@lbox_list[0].select_index)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def _line_array_to_hash(line)
 | 
			
		||||
    result = {}
 | 
			
		||||
    @name_index.each_pair{|label, indices|
 | 
			
		||||
      if indices.size == 1
 | 
			
		||||
	result[label] = line[indices[0]]
 | 
			
		||||
      else
 | 
			
		||||
	result[label] = indices.collect{|index| line[index]}
 | 
			
		||||
      end
 | 
			
		||||
    }
 | 
			
		||||
    result
 | 
			
		||||
  end
 | 
			
		||||
  private :_line_array_to_hash
 | 
			
		||||
 | 
			
		||||
  def get_by_hash(*idx)
 | 
			
		||||
    get_result = get(*idx)
 | 
			
		||||
    if idx.size == 1
 | 
			
		||||
      _line_array_to_hash(get_result)
 | 
			
		||||
    else
 | 
			
		||||
      get_result.collect{|line| _line_array_to_hash(line)}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def insert(idx, *lines)
 | 
			
		||||
    lbox_ins = []
 | 
			
		||||
    (0..@lbox_list.size).each{lbox_ins << []}
 | 
			
		||||
 | 
			
		||||
    if idx.kind_of?(Integer)
 | 
			
		||||
      idx = "#{idx}.0"
 | 
			
		||||
    else
 | 
			
		||||
      idx = idx.to_s
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if @lbox_list[0].index('1.0 + 1 char') == @lbox_list[0].index('end')
 | 
			
		||||
      cr = ""
 | 
			
		||||
    else
 | 
			
		||||
      cr = "\n"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    lines.each{|line|
 | 
			
		||||
      if line.kind_of? Hash
 | 
			
		||||
	array = []
 | 
			
		||||
	@name_index.each_pair{|label, indices|
 | 
			
		||||
	  if indices.size == 1
 | 
			
		||||
	    array[indices[0]] = line[label]
 | 
			
		||||
	  else
 | 
			
		||||
	    if line[label].kind_of? Array
 | 
			
		||||
	      indices.each_with_index{|index, num| 
 | 
			
		||||
		array[index] = line[label][num]
 | 
			
		||||
	      }
 | 
			
		||||
	    else
 | 
			
		||||
	      array[indices[0]] = line[label]
 | 
			
		||||
	    end
 | 
			
		||||
	  end
 | 
			
		||||
	}
 | 
			
		||||
	line = array
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @name_index.each_pair{|label, indices|
 | 
			
		||||
	if indices.size == 1
 | 
			
		||||
	  lbox_ins[indices[0]] << line[indices[0]]
 | 
			
		||||
	else
 | 
			
		||||
	  indices.each{|index| lbox_ins[index] << line[index]}
 | 
			
		||||
	end
 | 
			
		||||
      }
 | 
			
		||||
    }	
 | 
			
		||||
 | 
			
		||||
    @lbox_list.each_with_index{|lbox, index| 
 | 
			
		||||
      lbox.insert(idx, cr + lbox_ins[index].join("\n")) if lbox_ins[index]
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def select_clear(first, last=None)
 | 
			
		||||
    @lbox_list.each{|lbox| lbox.sel_clear(first, last=None)}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def select_set(first, last=None)
 | 
			
		||||
    @lbox_list.each{|lbox| lbox.sel_set(first, last=None)}
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ###########################################
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  def reconstruct(height, width)
 | 
			
		||||
    if @keep_minsize && width <= @width_total
 | 
			
		||||
      @f_title.width(@width_total)
 | 
			
		||||
      @f_lbox.width(@width_total)
 | 
			
		||||
      @f_hscr.width(@width_total) if @show_each_hscr
 | 
			
		||||
      @window_width = @width_total
 | 
			
		||||
    else
 | 
			
		||||
      @f_title.width(width)
 | 
			
		||||
      @f_lbox.width(width)
 | 
			
		||||
      @f_hscr.width(width) if @show_each_hscr
 | 
			
		||||
      @window_width = width
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    @f_lbox.height(height)
 | 
			
		||||
 | 
			
		||||
    @c_title.scrollregion(@w_title.bbox)
 | 
			
		||||
    @c_lbox.scrollregion(@w_lbox.bbox)
 | 
			
		||||
    @c_hscr.scrollregion(@w_hscr.bbox) if @show_each_hscr
 | 
			
		||||
 | 
			
		||||
    (0..(@rel_list.size - 2)).each{|idx|
 | 
			
		||||
      title, lbox, hscr = @base_list[idx]
 | 
			
		||||
      title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
 | 
			
		||||
      lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx], 
 | 
			
		||||
		 'relheight'=>1.0)
 | 
			
		||||
      hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx])
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def resize(x)
 | 
			
		||||
    idx = @sel_sash
 | 
			
		||||
    return if idx == 0
 | 
			
		||||
 | 
			
		||||
    # adjustment of relative positioning
 | 
			
		||||
    delta = (x - @x) / @frame_width
 | 
			
		||||
    if delta < @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
 | 
			
		||||
      delta = @rel_list[idx-1] - @rel_list[idx] + (2*@sash/@frame_width)
 | 
			
		||||
    elsif delta > @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
 | 
			
		||||
      delta = @rel_list[idx+1] - @rel_list[idx] - (2*@sash/@frame_width)
 | 
			
		||||
    end
 | 
			
		||||
    @rel_list[idx] += delta
 | 
			
		||||
 | 
			
		||||
    # adjustment of leftside widget of the sash
 | 
			
		||||
    title, lbox, hscr = @base_list[idx - 1]
 | 
			
		||||
    title.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
 | 
			
		||||
    lbox.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1], 'relheight'=>1.0)
 | 
			
		||||
    hscr.place('relwidth'=>@rel_list[idx] - @rel_list[idx-1])
 | 
			
		||||
 | 
			
		||||
    # adjustment of rightside widget of the sash
 | 
			
		||||
    title, lbox, hscr = @base_list[idx]
 | 
			
		||||
    title.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx], 
 | 
			
		||||
		'relx'=>@rel_list[idx])
 | 
			
		||||
    lbox.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx], 
 | 
			
		||||
	       'relx'=>@rel_list[idx], 'relheight'=>1.0)
 | 
			
		||||
    hscr.place('relwidth'=>@rel_list[idx+1] - @rel_list[idx], 
 | 
			
		||||
	       'relx'=>@rel_list[idx])
 | 
			
		||||
 | 
			
		||||
    # update reference position
 | 
			
		||||
    @x = x
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def motion_cb(w, x, idx)
 | 
			
		||||
    if x <= @sash && idx > 0
 | 
			
		||||
      w.cursor 'sb_h_double_arrow'
 | 
			
		||||
      @mode = :sash
 | 
			
		||||
      @sel_sash = idx
 | 
			
		||||
    elsif x >= w.winfo_width - @sash && idx < @lbox_total - 1
 | 
			
		||||
      w.cursor 'sb_h_double_arrow'
 | 
			
		||||
      @mode = :sash
 | 
			
		||||
      @sel_sash = idx + 1
 | 
			
		||||
    else
 | 
			
		||||
      w.cursor ""
 | 
			
		||||
      @mode = :title
 | 
			
		||||
      @sel_sash = 0
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def title_binding(title, index)
 | 
			
		||||
    title.bind('Motion', proc{|w, x, idx| motion_cb(w, x, idx.to_i)}, 
 | 
			
		||||
	       "%W %x #{index}")
 | 
			
		||||
 | 
			
		||||
    title.bind('Enter', proc{|w, x, idx| motion_cb(w, x, idx.to_i)}, 
 | 
			
		||||
	       "%W %x #{index}")
 | 
			
		||||
 | 
			
		||||
    title.bind('Leave', proc{|w| w.cursor ""}, "%W")
 | 
			
		||||
 | 
			
		||||
    title.bind('Button-1', 
 | 
			
		||||
	       proc{|w, x| 
 | 
			
		||||
		 if @mode == :sash
 | 
			
		||||
		   @x = x
 | 
			
		||||
		   @frame_width = TkWinfo.width(@f_title).to_f
 | 
			
		||||
		 else
 | 
			
		||||
		   title.relief 'sunken'
 | 
			
		||||
		 end
 | 
			
		||||
	       }, 
 | 
			
		||||
	       '%W %X')
 | 
			
		||||
 | 
			
		||||
    title.bind('ButtonRelease-1', 
 | 
			
		||||
	       proc{|w, x, idx| 
 | 
			
		||||
		 i = idx.to_i
 | 
			
		||||
		 if @mode == :title && @title_cmd[i].kind_of?(Proc)
 | 
			
		||||
		   @title_cmd[i].call
 | 
			
		||||
		 end
 | 
			
		||||
		 title.relief 'raised'
 | 
			
		||||
		 motion_cb(w,x,i)
 | 
			
		||||
	       }, 
 | 
			
		||||
	       "%W %x #{index}")
 | 
			
		||||
 | 
			
		||||
    title.bind('B1-Motion', proc{|x| resize(x) if @mode == :sash}, "%X")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  ########################
 | 
			
		||||
  def select_line(w, idx)
 | 
			
		||||
    @lbox_list.each{|l|
 | 
			
		||||
      l.select_clear(1, 'end')
 | 
			
		||||
      l.select_set(idx)
 | 
			
		||||
    }
 | 
			
		||||
    w.select_set(idx)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def select_shift(w, dir)
 | 
			
		||||
    head = w.index('@1,1').split('.')[0].to_i
 | 
			
		||||
    tail = w.index("@1,#{w.winfo_height - 1}").split('.')[0].to_i - 1
 | 
			
		||||
    idx = w.select_index + dir
 | 
			
		||||
    last = w.index('end - 1 char').split('.')[0].to_i
 | 
			
		||||
    if idx < 1
 | 
			
		||||
      idx = 1
 | 
			
		||||
    elsif idx > last
 | 
			
		||||
      idx = last
 | 
			
		||||
    end
 | 
			
		||||
    @lbox_list.each{|l|
 | 
			
		||||
      l.select_clear(1, 'end')
 | 
			
		||||
      l.select_set(idx)
 | 
			
		||||
    }
 | 
			
		||||
    if head > idx
 | 
			
		||||
      @lbox_list.each{|l| l.yview('scroll', -1, 'units')}
 | 
			
		||||
    elsif tail < idx
 | 
			
		||||
      @lbox_list.each{|l| l.yview('scroll', 1, 'units')}
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  ########################
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
################################################
 | 
			
		||||
# test
 | 
			
		||||
################################################
 | 
			
		||||
if __FILE__ == $0
 | 
			
		||||
  l = TkMultiColumnList.new(nil, 200, 
 | 
			
		||||
			    [ ['L1', 200, proc{p 'click L1'}], 
 | 
			
		||||
			      ['L2', 100], 
 | 
			
		||||
			      ['L3', 200] ], 
 | 
			
		||||
			    'width'=>350, 
 | 
			
		||||
			    #'titleforeground'=>'yellow', 
 | 
			
		||||
			    'titleforeground'=>'white', 
 | 
			
		||||
			    #'titlebackground'=>'navy',
 | 
			
		||||
			    'titlebackground'=>'blue',
 | 
			
		||||
			    'titlefont'=>'courier'
 | 
			
		||||
			    ).pack('fill'=>'both', 'expand'=>true)
 | 
			
		||||
  l.insert('end', [1,2,3])
 | 
			
		||||
  l.insert('end', [4,5,6])
 | 
			
		||||
  l.insert('end', [4,5,6], [4,5,6])
 | 
			
		||||
  l.insert('end', ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 
 | 
			
		||||
	           'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
 | 
			
		||||
                   'cccccccccccccccccccccccccccccccccccccccccccccccccccc'])
 | 
			
		||||
  l.insert('end', [1,2,3])
 | 
			
		||||
  l.insert('end', [4,5,6], [4,5,6])
 | 
			
		||||
  l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
 | 
			
		||||
  l.insert('end', [1,2,3])
 | 
			
		||||
  l.insert('end', [4,5,6], [4,5,6])
 | 
			
		||||
  l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
 | 
			
		||||
  l.insert('end', [1,2,3])
 | 
			
		||||
  l.insert('end', [4,5,6], [4,5,6])
 | 
			
		||||
  l.insert('end', ['aaaaaaaaaaaaaaa','bbbbbbbbbbbbbb','ccccccccccccccccc'])
 | 
			
		||||
  l.insert('end', [1,2,3])
 | 
			
		||||
  l.insert('end', [4,5,6], [4,5,6])
 | 
			
		||||
  p l.columns(1)
 | 
			
		||||
  p l.columns(1..3)
 | 
			
		||||
  p l.columns(1,2)
 | 
			
		||||
 | 
			
		||||
  l.command proc{|line_info| p line_info}
 | 
			
		||||
 | 
			
		||||
  Tk.mainloop
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +49,9 @@ class TkMultiListFrame < TkListbox
 | 
			
		|||
    @title_border = 3
 | 
			
		||||
    @h_l_thick = 0
 | 
			
		||||
 | 
			
		||||
    # init status
 | 
			
		||||
    @mode = :title
 | 
			
		||||
 | 
			
		||||
    # virtical scrollbar
 | 
			
		||||
=begin
 | 
			
		||||
    @v_scroll = TkScrollbar.new(@frame, 'highlightthickness'=>@h_l_thick, 
 | 
			
		||||
| 
						 | 
				
			
			@ -212,11 +215,11 @@ class TkMultiListFrame < TkListbox
 | 
			
		|||
    @h_scroll.assign(@c_title, @c_lbox, @c_hscr)
 | 
			
		||||
 | 
			
		||||
    # binding for listboxes
 | 
			
		||||
    @mode = {}
 | 
			
		||||
    @mode['browse']   = browse_mode_bindtag
 | 
			
		||||
    @mode['single']   = single_mode_bindtag
 | 
			
		||||
    @mode['extended'] = extended_mode_bindtag
 | 
			
		||||
    @mode['multiple'] = multiple_mode_bindtag
 | 
			
		||||
    @lbox_mode = {}
 | 
			
		||||
    @lbox_mode['browse']   = browse_mode_bindtag
 | 
			
		||||
    @lbox_mode['single']   = single_mode_bindtag
 | 
			
		||||
    @lbox_mode['extended'] = extended_mode_bindtag
 | 
			
		||||
    @lbox_mode['multiple'] = multiple_mode_bindtag
 | 
			
		||||
    @current_mode = 'browse'
 | 
			
		||||
    @lbox_list.each_with_index{|l, idx| 
 | 
			
		||||
      l.bind('Shift-Key-Left', 
 | 
			
		||||
| 
						 | 
				
			
			@ -233,7 +236,7 @@ class TkMultiListFrame < TkListbox
 | 
			
		|||
	       l.scan_dragto(x, y)
 | 
			
		||||
	     }, '%x %y')
 | 
			
		||||
 | 
			
		||||
      l.bindtags(l.bindtags.unshift(@mode[@current_mode]))
 | 
			
		||||
      l.bindtags(l.bindtags.unshift(@lbox_mode[@current_mode]))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bbox = @w_title.bbox
 | 
			
		||||
| 
						 | 
				
			
			@ -315,8 +318,8 @@ class TkMultiListFrame < TkListbox
 | 
			
		|||
  def mode(sel_mode)
 | 
			
		||||
    @lbox_list.each{|l| 
 | 
			
		||||
      tags = l.bindtags
 | 
			
		||||
      tags = tags - [ @mode[@current_mode] ]
 | 
			
		||||
      l.bindtags(tags.unshift(@mode[sel_mode]))
 | 
			
		||||
      tags = tags - [ @lbox_mode[@current_mode] ]
 | 
			
		||||
      l.bindtags(tags.unshift(@lbox_mode[sel_mode]))
 | 
			
		||||
      @current_mode = sel_mode
 | 
			
		||||
    }
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue