17db96d56Sopenharmony_cifrom tkinter import *
27db96d56Sopenharmony_cifrom tkinter.ttk import Frame, Scrollbar
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_cifrom idlelib import macosx
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciclass ScrolledList:
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci    default = "(None)"
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci    def __init__(self, master, **options):
127db96d56Sopenharmony_ci        # Create top frame, with scrollbar and listbox
137db96d56Sopenharmony_ci        self.master = master
147db96d56Sopenharmony_ci        self.frame = frame = Frame(master)
157db96d56Sopenharmony_ci        self.frame.pack(fill="both", expand=1)
167db96d56Sopenharmony_ci        self.vbar = vbar = Scrollbar(frame, name="vbar")
177db96d56Sopenharmony_ci        self.vbar.pack(side="right", fill="y")
187db96d56Sopenharmony_ci        self.listbox = listbox = Listbox(frame, exportselection=0,
197db96d56Sopenharmony_ci            background="white")
207db96d56Sopenharmony_ci        if options:
217db96d56Sopenharmony_ci            listbox.configure(options)
227db96d56Sopenharmony_ci        listbox.pack(expand=1, fill="both")
237db96d56Sopenharmony_ci        # Tie listbox and scrollbar together
247db96d56Sopenharmony_ci        vbar["command"] = listbox.yview
257db96d56Sopenharmony_ci        listbox["yscrollcommand"] = vbar.set
267db96d56Sopenharmony_ci        # Bind events to the list box
277db96d56Sopenharmony_ci        listbox.bind("<ButtonRelease-1>", self.click_event)
287db96d56Sopenharmony_ci        listbox.bind("<Double-ButtonRelease-1>", self.double_click_event)
297db96d56Sopenharmony_ci        if macosx.isAquaTk():
307db96d56Sopenharmony_ci            listbox.bind("<ButtonPress-2>", self.popup_event)
317db96d56Sopenharmony_ci            listbox.bind("<Control-Button-1>", self.popup_event)
327db96d56Sopenharmony_ci        else:
337db96d56Sopenharmony_ci            listbox.bind("<ButtonPress-3>", self.popup_event)
347db96d56Sopenharmony_ci        listbox.bind("<Key-Up>", self.up_event)
357db96d56Sopenharmony_ci        listbox.bind("<Key-Down>", self.down_event)
367db96d56Sopenharmony_ci        # Mark as empty
377db96d56Sopenharmony_ci        self.clear()
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci    def close(self):
407db96d56Sopenharmony_ci        self.frame.destroy()
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci    def clear(self):
437db96d56Sopenharmony_ci        self.listbox.delete(0, "end")
447db96d56Sopenharmony_ci        self.empty = 1
457db96d56Sopenharmony_ci        self.listbox.insert("end", self.default)
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci    def append(self, item):
487db96d56Sopenharmony_ci        if self.empty:
497db96d56Sopenharmony_ci            self.listbox.delete(0, "end")
507db96d56Sopenharmony_ci            self.empty = 0
517db96d56Sopenharmony_ci        self.listbox.insert("end", str(item))
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci    def get(self, index):
547db96d56Sopenharmony_ci        return self.listbox.get(index)
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci    def click_event(self, event):
577db96d56Sopenharmony_ci        self.listbox.activate("@%d,%d" % (event.x, event.y))
587db96d56Sopenharmony_ci        index = self.listbox.index("active")
597db96d56Sopenharmony_ci        self.select(index)
607db96d56Sopenharmony_ci        self.on_select(index)
617db96d56Sopenharmony_ci        return "break"
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci    def double_click_event(self, event):
647db96d56Sopenharmony_ci        index = self.listbox.index("active")
657db96d56Sopenharmony_ci        self.select(index)
667db96d56Sopenharmony_ci        self.on_double(index)
677db96d56Sopenharmony_ci        return "break"
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci    menu = None
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ci    def popup_event(self, event):
727db96d56Sopenharmony_ci        if not self.menu:
737db96d56Sopenharmony_ci            self.make_menu()
747db96d56Sopenharmony_ci        menu = self.menu
757db96d56Sopenharmony_ci        self.listbox.activate("@%d,%d" % (event.x, event.y))
767db96d56Sopenharmony_ci        index = self.listbox.index("active")
777db96d56Sopenharmony_ci        self.select(index)
787db96d56Sopenharmony_ci        menu.tk_popup(event.x_root, event.y_root)
797db96d56Sopenharmony_ci        return "break"
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci    def make_menu(self):
827db96d56Sopenharmony_ci        menu = Menu(self.listbox, tearoff=0)
837db96d56Sopenharmony_ci        self.menu = menu
847db96d56Sopenharmony_ci        self.fill_menu()
857db96d56Sopenharmony_ci
867db96d56Sopenharmony_ci    def up_event(self, event):
877db96d56Sopenharmony_ci        index = self.listbox.index("active")
887db96d56Sopenharmony_ci        if self.listbox.selection_includes(index):
897db96d56Sopenharmony_ci            index = index - 1
907db96d56Sopenharmony_ci        else:
917db96d56Sopenharmony_ci            index = self.listbox.size() - 1
927db96d56Sopenharmony_ci        if index < 0:
937db96d56Sopenharmony_ci            self.listbox.bell()
947db96d56Sopenharmony_ci        else:
957db96d56Sopenharmony_ci            self.select(index)
967db96d56Sopenharmony_ci            self.on_select(index)
977db96d56Sopenharmony_ci        return "break"
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ci    def down_event(self, event):
1007db96d56Sopenharmony_ci        index = self.listbox.index("active")
1017db96d56Sopenharmony_ci        if self.listbox.selection_includes(index):
1027db96d56Sopenharmony_ci            index = index + 1
1037db96d56Sopenharmony_ci        else:
1047db96d56Sopenharmony_ci            index = 0
1057db96d56Sopenharmony_ci        if index >= self.listbox.size():
1067db96d56Sopenharmony_ci            self.listbox.bell()
1077db96d56Sopenharmony_ci        else:
1087db96d56Sopenharmony_ci            self.select(index)
1097db96d56Sopenharmony_ci            self.on_select(index)
1107db96d56Sopenharmony_ci        return "break"
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_ci    def select(self, index):
1137db96d56Sopenharmony_ci        self.listbox.focus_set()
1147db96d56Sopenharmony_ci        self.listbox.activate(index)
1157db96d56Sopenharmony_ci        self.listbox.selection_clear(0, "end")
1167db96d56Sopenharmony_ci        self.listbox.selection_set(index)
1177db96d56Sopenharmony_ci        self.listbox.see(index)
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci    # Methods to override for specific actions
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci    def fill_menu(self):
1227db96d56Sopenharmony_ci        pass
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci    def on_select(self, index):
1257db96d56Sopenharmony_ci        pass
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ci    def on_double(self, index):
1287db96d56Sopenharmony_ci        pass
1297db96d56Sopenharmony_ci
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_cidef _scrolled_list(parent):  # htest #
1327db96d56Sopenharmony_ci    top = Toplevel(parent)
1337db96d56Sopenharmony_ci    x, y = map(int, parent.geometry().split('+')[1:])
1347db96d56Sopenharmony_ci    top.geometry("+%d+%d" % (x+200, y + 175))
1357db96d56Sopenharmony_ci    class MyScrolledList(ScrolledList):
1367db96d56Sopenharmony_ci        def fill_menu(self): self.menu.add_command(label="right click")
1377db96d56Sopenharmony_ci        def on_select(self, index): print("select", self.get(index))
1387db96d56Sopenharmony_ci        def on_double(self, index): print("double", self.get(index))
1397db96d56Sopenharmony_ci
1407db96d56Sopenharmony_ci    scrolled_list = MyScrolledList(top)
1417db96d56Sopenharmony_ci    for i in range(30):
1427db96d56Sopenharmony_ci        scrolled_list.append("Item %02d" % i)
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ciif __name__ == '__main__':
1457db96d56Sopenharmony_ci    from unittest import main
1467db96d56Sopenharmony_ci    main('idlelib.idle_test.test_scrolledlist', verbosity=2,)
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci    from idlelib.idle_test.htest import run
1497db96d56Sopenharmony_ci    run(_scrolled_list)
150