# One or more ScrolledLists with HSeparators between them.
# There is a hierarchical relationship between them:
# the right list displays the substructure of the selected item
# in the left list.

from Tkinter import *
from WindowList import ListedToplevel
from Separator import HSeparator
from ScrolledList import ScrolledList

class MultiScrolledLists:

    def __init__(self, root, nlists=2):
        assert nlists >= 1
        self.root = root
        self.nlists = nlists
        self.path = []
        # create top
        self.top = top = ListedToplevel(root)
        top.protocol("WM_DELETE_WINDOW", self.close)
        top.bind("<Escape>", self.close)
        self.settitle()
        # create frames and separators in between
        self.frames = []
        self.separators = []
        last = top
        for i in range(nlists-1):
            sepa = HSeparator(last)
            self.separators.append(sepa)
            frame, last = sepa.parts()
            self.frames.append(frame)
        self.frames.append(last)
        # create labels and lists
        self.labels = []
        self.lists = []
        for i in range(nlists):
            frame = self.frames[i]
            label = Label(frame, text=self.subtitle(i),
                relief="groove", borderwidth=2)
            label.pack(fill="x")
            self.labels.append(label)
            list = ScrolledList(frame, width=self.width(i),
                height=self.height(i))
            self.lists.append(list)
            list.on_select = \
                lambda index, i=i, self=self: self.on_select(index, i)
            list.on_double = \
                lambda index, i=i, self=self: self.on_double(index, i)
        # fill leftmost list (rest get filled on demand)
        self.fill(0)
        # XXX one after_idle isn't enough; two are...
        top.after_idle(self.call_pack_propagate_1)

    def call_pack_propagate_1(self):
        self.top.after_idle(self.call_pack_propagate)

    def call_pack_propagate(self):
        for frame in self.frames:
            frame.pack_propagate(0)

    def close(self, event=None):
        self.top.destroy()

    def settitle(self):
        short = self.shorttitle()
        long = self.longtitle()
        if short and long:
            title = short + " - " + long
        elif short:
            title = short
        elif long:
            title = long
        else:
            title = "Untitled"
        icon = short or long or title
        self.top.wm_title(title)
        self.top.wm_iconname(icon)

    def longtitle(self):
        # override this
        return "Multi Scrolled Lists"

    def shorttitle(self):
        # override this
        return None

    def width(self, i):
        # override this
        return 20

    def height(self, i):
        # override this
        return 10

    def subtitle(self, i):
        # override this
        return "Column %d" % i

    def fill(self, i):
        for k in range(i, self.nlists):
            self.lists[k].clear()
            self.labels[k].configure(text=self.subtitle(k))
        list = self.lists[i]
        l = self.items(i)
        for s in l:
            list.append(s)

    def on_select(self, index, i):
        item = self.lists[i].get(index)
        del self.path[i:]
        self.path.append(item)
        if i+1 < self.nlists:
            self.fill(i+1)

    def items(self, i):
        # override this
        l = []
        for k in range(10):
            s = str(k)
            if i > 0:
                s = self.path[i-1] + "." + s
            l.append(s)
        return l

    def on_double(self, index, i):
        pass


def main():
    root = Tk()
    quit = Button(root, text="Exit", command=root.destroy)
    quit.pack()
    MultiScrolledLists(root, 4)
    root.mainloop()

if __name__ == "__main__":
    main()
