Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / amd64 / lib / python2.4 / site-packages / Pmw / Pmw_1_2 / lib / PmwScrolledCanvas.py
CommitLineData
920dae64
AT
1import Tkinter
2import Pmw
3
4class ScrolledCanvas(Pmw.MegaWidget):
5 def __init__(self, parent = None, **kw):
6
7 # Define the megawidget options.
8 INITOPT = Pmw.INITOPT
9 optiondefs = (
10 ('borderframe', 0, INITOPT),
11 ('canvasmargin', 0, INITOPT),
12 ('hscrollmode', 'dynamic', self._hscrollMode),
13 ('labelmargin', 0, INITOPT),
14 ('labelpos', None, INITOPT),
15 ('scrollmargin', 2, INITOPT),
16 ('usehullsize', 0, INITOPT),
17 ('vscrollmode', 'dynamic', self._vscrollMode),
18 )
19 self.defineoptions(kw, optiondefs)
20
21 # Initialise the base class (after defining the options).
22 Pmw.MegaWidget.__init__(self, parent)
23
24 # Create the components.
25 self.origInterior = Pmw.MegaWidget.interior(self)
26
27 if self['usehullsize']:
28 self.origInterior.grid_propagate(0)
29
30 if self['borderframe']:
31 # Create a frame widget to act as the border of the canvas.
32 self._borderframe = self.createcomponent('borderframe',
33 (), None,
34 Tkinter.Frame, (self.origInterior,),
35 relief = 'sunken',
36 borderwidth = 2,
37 )
38 self._borderframe.grid(row = 2, column = 2, sticky = 'news')
39
40 # Create the canvas widget.
41 self._canvas = self.createcomponent('canvas',
42 (), None,
43 Tkinter.Canvas, (self._borderframe,),
44 highlightthickness = 0,
45 borderwidth = 0,
46 )
47 self._canvas.pack(fill = 'both', expand = 1)
48 else:
49 # Create the canvas widget.
50 self._canvas = self.createcomponent('canvas',
51 (), None,
52 Tkinter.Canvas, (self.origInterior,),
53 relief = 'sunken',
54 borderwidth = 2,
55 )
56 self._canvas.grid(row = 2, column = 2, sticky = 'news')
57
58 self.origInterior.grid_rowconfigure(2, weight = 1, minsize = 0)
59 self.origInterior.grid_columnconfigure(2, weight = 1, minsize = 0)
60
61 # Create the horizontal scrollbar
62 self._horizScrollbar = self.createcomponent('horizscrollbar',
63 (), 'Scrollbar',
64 Tkinter.Scrollbar, (self.origInterior,),
65 orient='horizontal',
66 command=self._canvas.xview
67 )
68
69 # Create the vertical scrollbar
70 self._vertScrollbar = self.createcomponent('vertscrollbar',
71 (), 'Scrollbar',
72 Tkinter.Scrollbar, (self.origInterior,),
73 orient='vertical',
74 command=self._canvas.yview
75 )
76
77 self.createlabel(self.origInterior, childCols = 3, childRows = 3)
78
79 # Initialise instance variables.
80 self._horizScrollbarOn = 0
81 self._vertScrollbarOn = 0
82 self.scrollTimer = None
83 self._scrollRecurse = 0
84 self._horizScrollbarNeeded = 0
85 self._vertScrollbarNeeded = 0
86 self.setregionTimer = None
87
88 # Check keywords and initialise options.
89 self.initialiseoptions()
90
91 def destroy(self):
92 if self.scrollTimer is not None:
93 self.after_cancel(self.scrollTimer)
94 self.scrollTimer = None
95 if self.setregionTimer is not None:
96 self.after_cancel(self.setregionTimer)
97 self.setregionTimer = None
98 Pmw.MegaWidget.destroy(self)
99
100 # ======================================================================
101
102 # Public methods.
103
104 def interior(self):
105 return self._canvas
106
107 def resizescrollregion(self):
108 if self.setregionTimer is None:
109 self.setregionTimer = self.after_idle(self._setRegion)
110
111 # ======================================================================
112
113 # Configuration methods.
114
115 def _hscrollMode(self):
116 # The horizontal scroll mode has been configured.
117
118 mode = self['hscrollmode']
119
120 if mode == 'static':
121 if not self._horizScrollbarOn:
122 self._toggleHorizScrollbar()
123 elif mode == 'dynamic':
124 if self._horizScrollbarNeeded != self._horizScrollbarOn:
125 self._toggleHorizScrollbar()
126 elif mode == 'none':
127 if self._horizScrollbarOn:
128 self._toggleHorizScrollbar()
129 else:
130 message = 'bad hscrollmode option "%s": should be static, dynamic, or none' % mode
131 raise ValueError, message
132
133 self._configureScrollCommands()
134
135 def _vscrollMode(self):
136 # The vertical scroll mode has been configured.
137
138 mode = self['vscrollmode']
139
140 if mode == 'static':
141 if not self._vertScrollbarOn:
142 self._toggleVertScrollbar()
143 elif mode == 'dynamic':
144 if self._vertScrollbarNeeded != self._vertScrollbarOn:
145 self._toggleVertScrollbar()
146 elif mode == 'none':
147 if self._vertScrollbarOn:
148 self._toggleVertScrollbar()
149 else:
150 message = 'bad vscrollmode option "%s": should be static, dynamic, or none' % mode
151 raise ValueError, message
152
153 self._configureScrollCommands()
154
155 # ======================================================================
156
157 # Private methods.
158
159 def _configureScrollCommands(self):
160 # If both scrollmodes are not dynamic we can save a lot of
161 # time by not having to create an idle job to handle the
162 # scroll commands.
163
164 # Clean up previous scroll commands to prevent memory leak.
165 tclCommandName = str(self._canvas.cget('xscrollcommand'))
166 if tclCommandName != '':
167 self._canvas.deletecommand(tclCommandName)
168 tclCommandName = str(self._canvas.cget('yscrollcommand'))
169 if tclCommandName != '':
170 self._canvas.deletecommand(tclCommandName)
171
172 if self['hscrollmode'] == self['vscrollmode'] == 'dynamic':
173 self._canvas.configure(
174 xscrollcommand=self._scrollBothLater,
175 yscrollcommand=self._scrollBothLater
176 )
177 else:
178 self._canvas.configure(
179 xscrollcommand=self._scrollXNow,
180 yscrollcommand=self._scrollYNow
181 )
182
183 def _scrollXNow(self, first, last):
184 self._horizScrollbar.set(first, last)
185 self._horizScrollbarNeeded = ((first, last) != ('0', '1'))
186
187 if self['hscrollmode'] == 'dynamic':
188 if self._horizScrollbarNeeded != self._horizScrollbarOn:
189 self._toggleHorizScrollbar()
190
191 def _scrollYNow(self, first, last):
192 self._vertScrollbar.set(first, last)
193 self._vertScrollbarNeeded = ((first, last) != ('0', '1'))
194
195 if self['vscrollmode'] == 'dynamic':
196 if self._vertScrollbarNeeded != self._vertScrollbarOn:
197 self._toggleVertScrollbar()
198
199 def _scrollBothLater(self, first, last):
200 # Called by the canvas to set the horizontal or vertical
201 # scrollbar when it has scrolled or changed scrollregion.
202
203 if self.scrollTimer is None:
204 self.scrollTimer = self.after_idle(self._scrollBothNow)
205
206 def _scrollBothNow(self):
207 # This performs the function of _scrollXNow and _scrollYNow.
208 # If one is changed, the other should be updated to match.
209 self.scrollTimer = None
210
211 # Call update_idletasks to make sure that the containing frame
212 # has been resized before we attempt to set the scrollbars.
213 # Otherwise the scrollbars may be mapped/unmapped continuously.
214 self._scrollRecurse = self._scrollRecurse + 1
215 self.update_idletasks()
216 self._scrollRecurse = self._scrollRecurse - 1
217 if self._scrollRecurse != 0:
218 return
219
220 xview = self._canvas.xview()
221 yview = self._canvas.yview()
222 self._horizScrollbar.set(xview[0], xview[1])
223 self._vertScrollbar.set(yview[0], yview[1])
224
225 self._horizScrollbarNeeded = (xview != (0.0, 1.0))
226 self._vertScrollbarNeeded = (yview != (0.0, 1.0))
227
228 # If both horizontal and vertical scrollmodes are dynamic and
229 # currently only one scrollbar is mapped and both should be
230 # toggled, then unmap the mapped scrollbar. This prevents a
231 # continuous mapping and unmapping of the scrollbars.
232 if (self['hscrollmode'] == self['vscrollmode'] == 'dynamic' and
233 self._horizScrollbarNeeded != self._horizScrollbarOn and
234 self._vertScrollbarNeeded != self._vertScrollbarOn and
235 self._vertScrollbarOn != self._horizScrollbarOn):
236 if self._horizScrollbarOn:
237 self._toggleHorizScrollbar()
238 else:
239 self._toggleVertScrollbar()
240 return
241
242 if self['hscrollmode'] == 'dynamic':
243 if self._horizScrollbarNeeded != self._horizScrollbarOn:
244 self._toggleHorizScrollbar()
245
246 if self['vscrollmode'] == 'dynamic':
247 if self._vertScrollbarNeeded != self._vertScrollbarOn:
248 self._toggleVertScrollbar()
249
250 def _toggleHorizScrollbar(self):
251
252 self._horizScrollbarOn = not self._horizScrollbarOn
253
254 interior = self.origInterior
255 if self._horizScrollbarOn:
256 self._horizScrollbar.grid(row = 4, column = 2, sticky = 'news')
257 interior.grid_rowconfigure(3, minsize = self['scrollmargin'])
258 else:
259 self._horizScrollbar.grid_forget()
260 interior.grid_rowconfigure(3, minsize = 0)
261
262 def _toggleVertScrollbar(self):
263
264 self._vertScrollbarOn = not self._vertScrollbarOn
265
266 interior = self.origInterior
267 if self._vertScrollbarOn:
268 self._vertScrollbar.grid(row = 2, column = 4, sticky = 'news')
269 interior.grid_columnconfigure(3, minsize = self['scrollmargin'])
270 else:
271 self._vertScrollbar.grid_forget()
272 interior.grid_columnconfigure(3, minsize = 0)
273
274 def _setRegion(self):
275 self.setregionTimer = None
276
277 region = self._canvas.bbox('all')
278 if region is not None:
279 canvasmargin = self['canvasmargin']
280 region = (region[0] - canvasmargin, region[1] - canvasmargin,
281 region[2] + canvasmargin, region[3] + canvasmargin)
282 self._canvas.configure(scrollregion = region)
283
284 # Need to explicitly forward this to override the stupid
285 # (grid_)bbox method inherited from Tkinter.Frame.Grid.
286 def bbox(self, *args):
287 return apply(self._canvas.bbox, args)
288
289Pmw.forwardmethods(ScrolledCanvas, Tkinter.Canvas, '_canvas')