from Tkinter import *
from rhtkinter import *

import string

class MultifieldListbox(RHFrame):
    def motion(self, e):
	count = 0
	line = e.widget.nearest(e.y)
	if (not self.onlyOne):
	    for field in self.fieldList:
		if (self.setmode):
		    self.listBoxes[count].select_set(line)
		else:
		    self.listBoxes[count].select_clear(line)
		count = count + 1
	else:
	    self.select(e)

    def select(self, e):
	line = e.widget.nearest(e.y)

	if (self.onlyOne):
	    self.setmode = 1
	else:
	    selected = e.widget.curselection()
	    self.setmode = 1
	    for item in selected:
		if (atoi(item) == line):
		    self.setmode = 0
		    break

	count = 0
	for field in self.fieldList:
	    if (self.listBoxes[count] != e.widget):
		if (self.onlyOne):
		    self.listBoxes[count].select_clear('0', 'end')

		if (self.setmode):
		    self.listBoxes[count].select_set(line)
		else:
		    self.listBoxes[count].select_clear(line)
	    count = count + 1

    def selectLine(self, line):
	count = 0
	for field in self.fieldList:
	    if (self.onlyOne):
		self.listBoxes[count].select_clear('0', 'end')

	    self.listBoxes[count].select_set(line)

	    count = count + 1

    def curselection(self):
	return self.listBoxes[0].curselection()

    def bind(self, pattern, action):
	for count in range(0, len(self.fieldList)):
	    self.listBoxes[count].bind(pattern, action)

    def delete(self, first, last=None):
	for count in range(0, len(self.fieldList)):
	    self.listBoxes[count].delete(first, last)

    def vscroll(self, *what):
	count = 0
	for field in self.fieldList:
	    apply(self.tk.call, (self.listBoxes[count]._w, 'yview')+what)
	    count = count + 1

    def createWidgets(self, fieldList):
	self['border'] = '2'
	self['relief'] = 'sunken'
	self.fieldList = fieldList
	count = 0
	self.listBoxes = []
	self.scrollbar = Scrollbar(self, { 'command' : self.vscroll } )
	for field in self.fieldList:
	    (title, width, expand) = field
	    frame = Frame(self)
	    title = Label(frame, { 'text' : title, 'relief' : 'raised' } )
	    title.pack({ 'fill' : 'x' })
	    self.listBoxes.append(RHListbox(frame,
					  { 'relief' : 'flat' ,
					    'exportselection' : '0' ,
					    'width' : "%d" % width,
					    'yscrollcommand' : 
						self.scrollbar.set } ) )
	    self.listBoxes[count].bind('<1>', self.select)
	    self.listBoxes[count].bind('<B1-Motion>', self.motion)
	    self.listBoxes[count].bind('<2>', self.select)
	    self.listBoxes[count].bind('<B2-Motion>', self.motion)
	    self.listBoxes[count].pack( { 'expand' : '1', 'fill' : 'both' } )
	    frame.pack( { 'side' : 'left', 'expand' : '1', 'fill' : 'both' } )
	    count = count + 1
	self.scrollbar.pack( { 'side' : 'left', 'fill' : 'y' } )

    def addItems(self, list):
	for tuple in list:
	    self.insert(tuple)

    def insert(self, tuple, where = 'end'):
	which = 0
	for item in tuple:
	    self.listBoxes[which].insert(where, item)
	    which = which + 1

    def deactivate(self):
	for l in self.listBoxes:
	    l.bind('<1>', self.noevent)
	    l.bind('<B1-Motion>', self.noevent)

    def noevent(self, e):
	pass

    def clear(self):
	for l in self.listBoxes:
	    l.delete('0', 'end')

    def getItems(self, row):
	tuple = ()
	for listbox in self.listBoxes:
	    tuple = tuple + (listbox.get("%d" % row), )
	return tuple

    def getAllItems(self):
	list = []
	for i in range(0, string.atoi(self.listBoxes[0].index('end'))):
	    list.append(self.getItems(i))
	return list

    def getSelectedItems(self):
	list = []
	for i in self.listBoxes[0].curselection():
	    list.append(self.getItems(string.atoi(i)))
	return list

    def changeField(self, row, col, string):
	s = self.listBoxes[col].curselection()
	self.listBoxes[col].delete("%d" % row)
	self.listBoxes[col].insert("%d" % row, string)
	self.listBoxes[col].select_clear('0', 'end')
	self.listBoxes[col].select_set(s)

    def allowMultiple(self):
	self.onlyOne = 0
	for listbox in self.listBoxes:
	    listbox['selectmode'] = 'multiple'

    def __init__(self, Master = None, fieldList):
	Frame.__init__(self, Master)
	self.createWidgets(fieldList)
	self.onlyOne = 1
