#!/usr/bin/env python

from Tkinter import *
import Pmw

class HistoryCombo(Pmw.ComboBox):
	def __init__(self, parent = None, **kw):
		optiondefs = (
			('completion', 1, None),
			)
		self.defineoptions(kw, optiondefs)
		Pmw.ComboBox.__init__(self, parent)

		# Initialize instance
		_registerWidget(self.component('entry'), self)

		# Construct keybindings
		self.bindkeys()
		self.component('entry').bindtags(self.component('entry').bindtags()
			+ ('HistoryPost',))

		# Check keywords and initialise options.
		self.initialiseoptions(HistoryCombo)
	
	def destroy(self):
		_deregisterEntryField(self.component('entry'))
		Pmw.ComboBox.destroy(self)
	
	def bindkeys(self):
		self.bind_class('HistoryPost', '<KeyPress>', _postProcess)
	
	def _postProcess(self, event):
		if not self['completion']:
			return
		if not event.char or `event.char`[1] == '\\':
			return
		currentstr = self.get()
		if not currentstr:
			# Don't complete on empty string
			return
		# Sort by length, so that shorter matches show up first
		history_list = list(self.get(0, 'end'))
		history_list.sort(lambda x, y: cmp(len(x), len(y)))
		for item in history_list:
			if currentstr == item[:len(currentstr)]:
				completion = item[len(currentstr):]
				here = self.component('entry').index('end')
				self.component('entry').insert('end', completion)
				self.component('entry').selection_range(here, 'end')
				self.component('entry').icursor('end')
				return

_entryCache = {}

def _registerWidget(entrywidget, parentwidget):
    # Register a parent widget for an Entry widget
    _entryCache[entrywidget] = parentwidget

def _deregisterEntryField(entrywidget):
    # Deregister an Entry widget
    del _entryCache[entrywidget]

def _postProcess(event, *args):
    # Forward postprocess events for an Entry to its HistoryCombo
    # The function specified by the 'command' option may have destroyed
    # the megawidget in a binding earlier in bindtags, so need to check.
    if _entryCache.has_key(event.widget):
        _entryCache[event.widget]._postProcess(event)

def main():
	a = HistoryCombo()
	a.pack()
	b = HistoryCombo()
	b.pack(side=TOP)
	a.mainloop()

if __name__ == '__main__':
	main()

