Home | History | Annotate | Download | only in idlelib
      1 from tkinter import *
      2 from tkinter.ttk import Frame, Scrollbar
      3 
      4 from idlelib import macosx
      5 
      6 
      7 class ScrolledList:
      8 
      9     default = "(None)"
     10 
     11     def __init__(self, master, **options):
     12         # Create top frame, with scrollbar and listbox
     13         self.master = master
     14         self.frame = frame = Frame(master)
     15         self.frame.pack(fill="both", expand=1)
     16         self.vbar = vbar = Scrollbar(frame, name="vbar")
     17         self.vbar.pack(side="right", fill="y")
     18         self.listbox = listbox = Listbox(frame, exportselection=0,
     19             background="white")
     20         if options:
     21             listbox.configure(options)
     22         listbox.pack(expand=1, fill="both")
     23         # Tie listbox and scrollbar together
     24         vbar["command"] = listbox.yview
     25         listbox["yscrollcommand"] = vbar.set
     26         # Bind events to the list box
     27         listbox.bind("<ButtonRelease-1>", self.click_event)
     28         listbox.bind("<Double-ButtonRelease-1>", self.double_click_event)
     29         if macosx.isAquaTk():
     30             listbox.bind("<ButtonPress-2>", self.popup_event)
     31             listbox.bind("<Control-Button-1>", self.popup_event)
     32         else:
     33             listbox.bind("<ButtonPress-3>", self.popup_event)
     34         listbox.bind("<Key-Up>", self.up_event)
     35         listbox.bind("<Key-Down>", self.down_event)
     36         # Mark as empty
     37         self.clear()
     38 
     39     def close(self):
     40         self.frame.destroy()
     41 
     42     def clear(self):
     43         self.listbox.delete(0, "end")
     44         self.empty = 1
     45         self.listbox.insert("end", self.default)
     46 
     47     def append(self, item):
     48         if self.empty:
     49             self.listbox.delete(0, "end")
     50             self.empty = 0
     51         self.listbox.insert("end", str(item))
     52 
     53     def get(self, index):
     54         return self.listbox.get(index)
     55 
     56     def click_event(self, event):
     57         self.listbox.activate("@%d,%d" % (event.x, event.y))
     58         index = self.listbox.index("active")
     59         self.select(index)
     60         self.on_select(index)
     61         return "break"
     62 
     63     def double_click_event(self, event):
     64         index = self.listbox.index("active")
     65         self.select(index)
     66         self.on_double(index)
     67         return "break"
     68 
     69     menu = None
     70 
     71     def popup_event(self, event):
     72         if not self.menu:
     73             self.make_menu()
     74         menu = self.menu
     75         self.listbox.activate("@%d,%d" % (event.x, event.y))
     76         index = self.listbox.index("active")
     77         self.select(index)
     78         menu.tk_popup(event.x_root, event.y_root)
     79         return "break"
     80 
     81     def make_menu(self):
     82         menu = Menu(self.listbox, tearoff=0)
     83         self.menu = menu
     84         self.fill_menu()
     85 
     86     def up_event(self, event):
     87         index = self.listbox.index("active")
     88         if self.listbox.selection_includes(index):
     89             index = index - 1
     90         else:
     91             index = self.listbox.size() - 1
     92         if index < 0:
     93             self.listbox.bell()
     94         else:
     95             self.select(index)
     96             self.on_select(index)
     97         return "break"
     98 
     99     def down_event(self, event):
    100         index = self.listbox.index("active")
    101         if self.listbox.selection_includes(index):
    102             index = index + 1
    103         else:
    104             index = 0
    105         if index >= self.listbox.size():
    106             self.listbox.bell()
    107         else:
    108             self.select(index)
    109             self.on_select(index)
    110         return "break"
    111 
    112     def select(self, index):
    113         self.listbox.focus_set()
    114         self.listbox.activate(index)
    115         self.listbox.selection_clear(0, "end")
    116         self.listbox.selection_set(index)
    117         self.listbox.see(index)
    118 
    119     # Methods to override for specific actions
    120 
    121     def fill_menu(self):
    122         pass
    123 
    124     def on_select(self, index):
    125         pass
    126 
    127     def on_double(self, index):
    128         pass
    129 
    130 
    131 def _scrolled_list(parent):  # htest #
    132     top = Toplevel(parent)
    133     x, y = map(int, parent.geometry().split('+')[1:])
    134     top.geometry("+%d+%d" % (x+200, y + 175))
    135     class MyScrolledList(ScrolledList):
    136         def fill_menu(self): self.menu.add_command(label="right click")
    137         def on_select(self, index): print("select", self.get(index))
    138         def on_double(self, index): print("double", self.get(index))
    139 
    140     scrolled_list = MyScrolledList(top)
    141     for i in range(30):
    142         scrolled_list.append("Item %02d" % i)
    143 
    144 if __name__ == '__main__':
    145     from unittest import main
    146     main('idlelib.idle_test.test_scrolledlist', verbosity=2,)
    147 
    148     from idlelib.idle_test.htest import run
    149     run(_scrolled_list)
    150