-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathscrolledlist.py
164 lines (144 loc) · 5.38 KB
/
scrolledlist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
"""scrolledlist.py: A Tkinter widget combining a Listbox with Scrollbar(s).
For details, see:
http://www.nmt.edu/tcc/help/lang/python/examples/scrolledlist/
"""
#================================================================
# Imports
#----------------------------------------------------------------
from Tkinter import *
#================================================================
# Manifest constants
#----------------------------------------------------------------
DEFAULT_WIDTH = "40"
DEFAULT_HEIGHT = "25"
class ScrolledList(Frame):
"""A compound widget containing a listbox and up to two scrollbars.
State/invariants:
.listbox: [ The Listbox widget ]
.vScrollbar:
[ if self has a vertical scrollbar ->
that scrollbar
else -> None ]
.hScrollbar:
[ if self has a vertical scrollbar ->
that scrollbar
else -> None ]
.callback: [ as passed to constructor ]
.vscroll: [ as passed to constructor ]
.hscroll: [ as passed to constructor ]
"""
def __init__ ( self, master=None, width=DEFAULT_WIDTH,
height=DEFAULT_HEIGHT, vscroll=1, hscroll=0, callback=None ):
"""Constructor for ScrolledList.
"""
#-- 1 --
# [ self := a new Frame widget child of master ]
Frame.__init__ ( self, master )
#-- 2 --
self.width = width
self.height = height
self.vscroll = vscroll
self.hscroll = hscroll
self.callback = callback
#-- 3 --
# [ self := self with all widgets created and registered ]
self.__createWidgets()
def __createWidgets ( self ):
"""Lay out internal widgets.
"""
#-- 1 --
# [ if self.vscroll ->
# self := self with a vertical Scrollbar widget added
# self.vScrollbar := that widget ]
# else -> I ]
if self.vscroll:
self.vScrollbar = Scrollbar ( self, orient=VERTICAL )
self.vScrollbar.grid ( row=0, column=1, sticky=N+S )
#-- 2 --
# [ if self.hscroll ->
# self := self with a horizontal Scrollbar widget added
# self.hScrollbar := that widget
# else -> I ]
if self.hscroll:
self.hScrollbar = Scrollbar ( self, orient=HORIZONTAL )
self.hScrollbar.grid ( row=1, column=0, sticky=E+W )
#-- 3 --
# [ self := self with a Listbox widget added
# self.listbox := that widget ]
self.listbox = Listbox ( self, relief=SUNKEN,
width=self.width, height=self.height,
borderwidth=2 )
self.listbox.grid ( row=0, column=0 )
#-- 4 --
# [ if self.vscroll ->
# self.listbox := self.listbox linked so that
# self.vScrollbar can reposition it ]
# self.vScrollbar := self.vScrollbar linked so that
# self.listbox can reposition it
# else -> I ]
if self.vscroll:
self.listbox["yscrollcommand"] = self.vScrollbar.set
self.vScrollbar["command"] = self.listbox.yview
#-- 5 --
# [ if self.hscroll ->
# self.listbox := self.listbox linked so that
# self.hScrollbar can reposition it ]
# self.hScrollbar := self.hScrollbar linked so that
# self.listbox can reposition it
# else -> I ]
if self.hscroll:
self.listbox["xscrollcommand"] = self.hScrollbar.set
self.hScrollbar["command"] = self.listbox.xview
#-- 6 --
# [ self.listbox := self.listbox with an event handler
# for button-1 clicks that causes self.callback
# to be called if there is one ]
self.listbox.bind ( "<Button-1>", self.__clickHandler )
def __clickHandler ( self, event ):
"""Called when the user clicks on a line in the listbox.
"""
#-- 1 --
if not self.callback:
return
#-- 2 --
# [ call self.callback(c) where c is the line index
# corresponding to event.y ]
lineNo = self.listbox.nearest ( event.y )
self.callback ( lineNo )
#-- 3 --
self.listbox.focus_set()
def count ( self ):
"""Return the number of lines in use in the listbox.
"""
return self.listbox.size()
def __getitem__ ( self, k ):
"""Get the (k)th line from the listbox.
"""
#-- 1 --
if ( 0 <= k < self.count() ):
return self.listbox.get ( k )
else:
raise IndexError, ( "ScrolledList[%d] out of range." % k )
def append ( self, text ):
"""Append a line to the listbox.
"""
self.listbox.insert ( END, text )
def insert ( self, linex, text ):
"""Insert a line between two existing lines.
"""
#-- 1 --
if 0 <= linex < self.count():
where = linex
else:
where = END
#-- 2 --
self.listbox.insert ( where, text )
def delete ( self, linex ):
"""Delete a line from the listbox.
"""
if 0 <= linex < self.count():
self.listbox.delete ( linex )
def clear ( self ):
"""Remove all lines.
"""
self.listbox.delete ( 0, END )