summaryrefslogtreecommitdiff
path: root/uitools/Scrolled.py
diff options
context:
space:
mode:
Diffstat (limited to 'uitools/Scrolled.py')
-rw-r--r--uitools/Scrolled.py184
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()