blob: d0b66107aca4ebfcba6ab7e184c3b80379b2145c [file] [log] [blame]
Georg Brandl14fc4272008-05-17 18:39:55 +00001from tkinter import *
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -04002from idlelib import macosx
Terry Jan Reedy01e35752016-06-10 18:19:21 -04003from tkinter.ttk import Scrollbar
David Scherer7aced172000-08-15 01:13:23 +00004
5class ScrolledList:
Kurt B. Kaiserbdaac362001-07-14 01:23:30 +00006
David Scherer7aced172000-08-15 01:13:23 +00007 default = "(None)"
8
9 def __init__(self, master, **options):
10 # Create top frame, with scrollbar and listbox
11 self.master = master
12 self.frame = frame = Frame(master)
13 self.frame.pack(fill="both", expand=1)
14 self.vbar = vbar = Scrollbar(frame, name="vbar")
15 self.vbar.pack(side="right", fill="y")
16 self.listbox = listbox = Listbox(frame, exportselection=0,
17 background="white")
18 if options:
19 listbox.configure(options)
20 listbox.pack(expand=1, fill="both")
21 # Tie listbox and scrollbar together
22 vbar["command"] = listbox.yview
23 listbox["yscrollcommand"] = vbar.set
24 # Bind events to the list box
25 listbox.bind("<ButtonRelease-1>", self.click_event)
26 listbox.bind("<Double-ButtonRelease-1>", self.double_click_event)
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -040027 if macosx.isAquaTk():
Terry Jan Reedy00e4ce32015-09-26 18:50:26 -040028 listbox.bind("<ButtonPress-2>", self.popup_event)
29 listbox.bind("<Control-Button-1>", self.popup_event)
30 else:
31 listbox.bind("<ButtonPress-3>", self.popup_event)
David Scherer7aced172000-08-15 01:13:23 +000032 listbox.bind("<Key-Up>", self.up_event)
33 listbox.bind("<Key-Down>", self.down_event)
34 # Mark as empty
35 self.clear()
36
37 def close(self):
38 self.frame.destroy()
39
40 def clear(self):
41 self.listbox.delete(0, "end")
42 self.empty = 1
43 self.listbox.insert("end", self.default)
44
45 def append(self, item):
46 if self.empty:
47 self.listbox.delete(0, "end")
48 self.empty = 0
49 self.listbox.insert("end", str(item))
50
51 def get(self, index):
52 return self.listbox.get(index)
53
54 def click_event(self, event):
55 self.listbox.activate("@%d,%d" % (event.x, event.y))
56 index = self.listbox.index("active")
57 self.select(index)
58 self.on_select(index)
59 return "break"
60
61 def double_click_event(self, event):
62 index = self.listbox.index("active")
63 self.select(index)
64 self.on_double(index)
65 return "break"
66
67 menu = None
68
69 def popup_event(self, event):
70 if not self.menu:
71 self.make_menu()
72 menu = self.menu
73 self.listbox.activate("@%d,%d" % (event.x, event.y))
74 index = self.listbox.index("active")
75 self.select(index)
76 menu.tk_popup(event.x_root, event.y_root)
77
78 def make_menu(self):
79 menu = Menu(self.listbox, tearoff=0)
80 self.menu = menu
81 self.fill_menu()
82
83 def up_event(self, event):
84 index = self.listbox.index("active")
85 if self.listbox.selection_includes(index):
86 index = index - 1
87 else:
88 index = self.listbox.size() - 1
89 if index < 0:
90 self.listbox.bell()
91 else:
92 self.select(index)
93 self.on_select(index)
94 return "break"
95
96 def down_event(self, event):
97 index = self.listbox.index("active")
98 if self.listbox.selection_includes(index):
99 index = index + 1
100 else:
101 index = 0
102 if index >= self.listbox.size():
103 self.listbox.bell()
104 else:
105 self.select(index)
106 self.on_select(index)
107 return "break"
108
109 def select(self, index):
110 self.listbox.focus_set()
111 self.listbox.activate(index)
112 self.listbox.selection_clear(0, "end")
113 self.listbox.selection_set(index)
114 self.listbox.see(index)
115
116 # Methods to override for specific actions
117
118 def fill_menu(self):
119 pass
120
121 def on_select(self, index):
122 pass
123
124 def on_double(self, index):
125 pass
126
127
Terry Jan Reedy01e35752016-06-10 18:19:21 -0400128def _scrolled_list(parent): # htest #
129 top = Toplevel(parent)
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -0400130 width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
Terry Jan Reedy01e35752016-06-10 18:19:21 -0400131 top.geometry("+%d+%d"%(x+200, y + 175))
David Scherer7aced172000-08-15 01:13:23 +0000132 class MyScrolledList(ScrolledList):
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -0400133 def fill_menu(self): self.menu.add_command(label="right click")
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000134 def on_select(self, index): print("select", self.get(index))
135 def on_double(self, index): print("double", self.get(index))
David Scherer7aced172000-08-15 01:13:23 +0000136
Terry Jan Reedy01e35752016-06-10 18:19:21 -0400137 scrolled_list = MyScrolledList(top)
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -0400138 for i in range(30):
139 scrolled_list.append("Item %02d" % i)
140
David Scherer7aced172000-08-15 01:13:23 +0000141if __name__ == '__main__':
Terry Jan Reedy01e35752016-06-10 18:19:21 -0400142 # At the moment, test_scrolledlist merely creates instance, like htest.
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -0400143 from idlelib.idle_test.htest import run
144 run(_scrolled_list)