diff options
Diffstat (limited to 'uitools/Scrolled.py')
-rw-r--r-- | uitools/Scrolled.py | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/uitools/Scrolled.py b/uitools/Scrolled.py new file mode 100644 index 0000000..e2c1a53 --- /dev/null +++ b/uitools/Scrolled.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python +###################################################################### +# Provides a generic window containing a frame and h/v scrollbars. +# Subclasses pack the scrollable/scannable thing into the frame and +# hook it up to the scrollbars by invoking setView. +# +# Mitch Chapman +#--------------------------------------------------------------------- +# $Log: Scrolled.py,v $ +# Revision 1.1 1996/12/01 22:58:54 mchapman +# Initial revision +# +###################################################################### + +__version__ = "$Revision: 1.1 $" + +import Tkinter; Tk=Tkinter +import string, time + +###################################################################### +# This is the scrolled window class. +###################################################################### +class T: + ################################################################## + # Specify the view to be scrolled by self. + ################################################################## + def _setView(self, newView): + self.view = newView + self.view.pack(in_=self.borderframe, fill='both', expand='yes') + self.vsPacking['before'] = self.view + # Attach the scrollbars. Note that scrollable must support + # these methods: xview, yview, xscrollcommand, yscrollcommand. + self.vscroll['command'] = self.view.yview + self.hscroll['command'] = self.view.xview + self.view['xscrollcommand'] = self.hscroll.set + self.view['yscrollcommand'] = self.vscroll.set + # Make sure the view is visible to the user + # Gotta explicitly use Tk.Misc.tkraise, because if the view + # is a canvas it defines its own tkraise -- whose purpose + # is to change the stacking order of canvas items. + Tk.Misc.tkraise(self.view, self.borderframe) + + ################################################################## + # Initialize a new instance. + ################################################################## + def __init__(self, master=None, view=None): + self.master = master + frame = self.frame = Tk.Frame(master) + + # The inner frame is provided because the Tk Text widget + # (<= Tk 4.1) wasn't smart enough to keep embedded windows from + # drawing over its border. This inner frame can take the place + # of the Text border in subclasses. + self.borderframe = Tk.Frame(frame, relief='sunken', bd=3, + highlightthickness=2) + + # Create the scrollbars. Record their packing rules for later + # use in dynamically mapping/unmapping scrollbars. + self.vsPacking = {'side':'right', 'fill':'y'} + vs = self.vscroll = Tk.Scrollbar(frame, orient='vertical', width=12) + + # The horizontal scrollbar goes into its own frame at the + # bottom. This offers the opportunity to stick a "spacer" + # frame to the right of the horizontal bar, so both scrollbars + # appear to stop at the edge of the contained view. + # This is stolen from "Practical Programming in Tcl and Tk," by + # Brent B. Welch. + padsize = self.padsize = (string.atoi(vs['width']) + + 2 *(string.atoi(vs['bd']) + + string.atoi(vs['highlightthickness']))) + hsFrame = self.hsFrame = Tk.Frame(frame) + # Here's the "spacer" frame. + hsPad = self.hsPad = Tk.Frame(hsFrame, width=padsize, height=padsize) + + hs = self.hscroll = Tk.Scrollbar(hsFrame, orient='horizontal', + width=12) + hs.pack(side='bottom', fill='x') + hsPad.pack(side='right', before=self.hscroll) + # This time, the packing is for self.hsFrame + self.hsFramePacking = {'before':vs, + 'side':'bottom', 'fill':'x', 'expand':'no'} + + apply(vs.pack, (), self.vsPacking) + self.borderframe.pack(fill='both', expand='yes') + apply(hsFrame.pack, (), self.hsFramePacking) + + self.view = None + self.hsPacked = 1 + self.vsPacked = 1 + + # Bad move: initializer invoking another method on self. + # At least _setView is named so as to indicate that subclasses + # should not override it directly... + if view: + self._setView(view) + + ################################################################## + # Install a scrollable thingy as the view for self. + # Note that you can change views on the fly, though it's up to + # you to remove any old views before setting the new one. + # newView should be a widget. It must provide Tkinter.Text-style + # methods xview() and yview(), and have configurable + # xscrollcommand and yscrollcommand attributes. + ################################################################## + def setView(self, newView): + self._setView(newView) + + +###################################################################### +# This is a scrolled text class. +###################################################################### +class Text(T): + ################################################################## + # Initialize a new instance. + ################################################################## + def __init__(self, master=None): + self.text = Tk.Text(master, relief='flat') + T.__init__(self, master, self.text) + +###################################################################### +# This is a scrolled canvas class. +###################################################################### +class Canvas(T): + ################################################################## + # Initialize a new instance. + ################################################################## + def __init__(self, master=None): + self.canvas = Tk.Canvas(master) + T.__init__(self, master, self.canvas) + +###################################################################### +# A List differs from other Scrolled types in that it has only a +# vertical scrollbar. (This despite the fact that lists with long +# entries could benefit from horizontal scrollbars...) +###################################################################### +class List(T): + ################################################################## + # Initialize a new instance. + ################################################################## + def __init__(self, master=None): + self.listbox = Tk.Listbox(master) + T.__init__(self, master, self.listbox) + self.hsFrame.forget() + self.view['xscrollcommand'] = None + self.hscroll['command'] = None + + +###################################################################### +# Main function for unit testing. +###################################################################### +def main(): + if 0: + # Here's one way to build a custom scrolled window: + scroller = T(view=Tk.Text(relief='flat', wrap='none')) + scroller.frame.pack(fill='both', expand='yes') + scroller.frame.master.title("Second Scroller") + Tk.mainloop() + else: + f = Tk.Frame() + t = Text(f) + # Turn off text wrapping so you can see the scrollbars at work. + t.text.configure(width=32, height=5, wrap='none') + t.text.insert('end', "This is a text.") + t.frame.pack(fill='both', expand='yes') + + c = Canvas(f) + c.canvas.configure(scrollregion="-100 -100 1000 1000") + c.canvas.create_text(0, 0, text="This is a canvas.", anchor="nw") + c.canvas.create_arc(300, 300, 400, 400, extent=270, fill='red') + c.canvas.create_oval(100, 100, 200, 200, fill='blue') + c.frame.pack(fill='both', expand='yes') + + l = List(f) + l.listbox.insert('end', "This is a listbox.") + for i in range(1, 21): + l.listbox.insert('end', "%d Mississippi" % i) + l.frame.pack(fill='both', expand='yes') + + f.master.title("Sample Scrolled Windows") + f.pack() + Tk.mainloop() + +if __name__ == "__main__": + main() |