Next / Previous / TCC home / NMT home

Source listing for scrollist.py

logo
"""scrollist.py:  Scrolled listbox compound widget

    $Revision: 1.1 $  $Date: 2000/12/19 01:39:29 $
"""

import string
from Tkinter import *

DEFAULT_WIDTH   =  40
DEFAULT_HEIGHT  =  25

class ScrolledList(Frame):
    """Scrolled list widget

      Exports:
        ScrolledList ( parent, width=None, height=None, callback=None ):
          [ if (parent is a Frame widget)
            and (width is the width in characters, defaulting to
            DEFAULT_WIDTH)
            and (height is the number of lines visible, defaulting to
            DEFAULT_HEIGHT)
            and (callback is a procedure with calling sequence
            callback ( lineNo )) ->
              parent  :=  parent with a new Frame added containing an empty
                          listbox and scrollbar, ungridded, that will call
                          callback(i) when double-clicked on the (i)th item
              return that new Frame ]
        .parent:    [ as passed to constructor ]
        .width:     [ as passed to constructor, or default ]
        .height:    [ as passed to constructor, or default ]
        .callback:  [ as passed to constructor ]
        .count():   [ returns number of lines in self ]
        self[i]:
          [ if 0 <= i < self.count() ->
              return the (i)th element of self's listbox
            else -> raise IndexError ]
        .append ( s ):
          [ if s is a string ->
              self  :=  self with s added as its new last line ]
        .insert ( linex, s ):
          [ if (linex is an integer) and (s is a string) ->
              if 0<=linex<=(number of lines in self) ->
                self  :=  self with s inserted as a new line before
                          position linex
              else ->
                self  :=  self with s added as its new last line ]
        .delete ( linex ):
          [ if (0<=linex<(number of lines in self)) ->
              self  :=  self with line linex deleted
            else -> I ]
        .clear():   [ self  :=  self without any lines ]

      State/Invariants:
        .listbox:   [ self's Listbox component ]
        .yscroll:   [ self's vertical scrollbar component ]
    """


# - - -   S c r o l l e d L i s t . _ _ i n i t _ _   - - -

    def __init__ ( self, master, width=None, height=None, callback=None ):
        """Constructor for ScrolledList compound widget
        """

        #-- 1 --
        # [ self  :=  a new Frame in master ]
        Frame.__init__ ( self, master )

        #-- 2 --
        self.master    =  master
        self.callback  =  callback

        if  width:  self.width  =  width
        else:       self.width  =  DEFAULT_WIDTH

        if  height:  self.height  =  height
        else:        self.height  =  DEFAULT_HEIGHT

        #-- 3 --
        # [ self  :=  self with all widgets added and gridded ]
        self.__createWidgets ()


# - - -   S c r o l l e d L i s t . _ _ c r e a t e W i d g e t s   - - -

    def __createWidgets ( self ):
        """ [ self  :=  self with all widgets added and gridded ]
        """

        #-- 1 --
        # [ self.yscroll  :=  a new vertical Scrollbar in self ]
        self.yscroll  =  Scrollbar ( self, orient=VERTICAL )
        self.yscroll.grid ( row=0, column=1, sticky=N+E+S )

        #-- 2 --
        # [ self.listbox  :=  a new Listbox in self with its vertical
        #                     scrolling slaved to self.yscroll, and
        #                     calling self.__pickHandler() when a line
        #                     is double-clicked ]
        self.listbox  =  Listbox ( self, relief=SUNKEN,
            width=self.width, height=self.height, borderwidth=2,
            yscrollcommand=self.yscroll.set )
        self.listbox.grid ( row=0, column=0, sticky=N+W+S )
        self.listbox.bind ( "<Double-Button-1>", self.__pickHandler )
        self.yscroll["command"]  =  self.listbox.yview


# - - -   S c r o l l e d L i s t . _ _ p i c k H a n d l e r   - - -

    def __pickHandler ( self, event ):
        """Handler for double-clicking on self.listbox
        """

        #-- 1 --
        if  self.callback is None:
            return

        #-- 2 --
        # [ if there is a current selection ->
        #     linex  :=  its index as an integer
        #   else ->
        #     return ]
        curSel  =  self.listbox.curselection()
        if  len(curSel) == 0:
            return
        else:
            linex  =  string.atoi(curSel[0])

        #-- 3 --
        self.callback ( linex )


# - - -   S c r o l l e d L i s t . c o u n t   - - -

    def count ( self ):
        """Returns the number of lines in self's listbox

            NOTE:  Originally I called this method __len__(), so that
            anyone could use the len() built-in function to get the
            number of entries.  But doing so led to bizarre bugs inside
            the basic Tkinter Widget class.  Apparently someone needs
            to call len() on Frame widgets, and my overriding it made
            something break.
        """
        return self.listbox.size()


# - - -   S c r o l l e d L i s t . _ _ g e t i t e m _ _    - -

    def __getitem__ ( self, k ):
        """Get the (k)th item from self's listbox
        """
        if  not ( 0 <= k < self.count() ):
            raise IndexError, ( "ScrolledList[%d] out of range" % k )
        else:
            return self.listbox.get ( k )


# - - -   S c r o l l e d L i s t . a p p e n d   - - -

    def append ( self, s ):
        """Add s as the new last element of self's listbox
        """
        self.listbox.insert ( END, s )


# - - -   S c r o l l e d L i s t . i n s e r t   - - -

    def insert ( self, linex, s ):
        """Insert s before position linex
        """

        #-- 1 --
        if  not ( 0 <= linex < self.count() ):
            where  =  END
        else:
            where  =  linex

        #-- 2 --
        self.listbox.insert ( where, s )


# - - -   S c r o l l e d L i s t . d e l e t e   - - -

    def delete ( self, linex ):
        """Delete a line from self's listbox
        """
        #-- 1 --
        if  not ( 0 <= linex < self.count() ):
            return

        #-- 2 --
        self.listbox.delete ( linex )


# - - -   S c r o l l e d L i s t . c l e a r   - - -

    def clear ( self ):
        """Delete all lines from self's listbox
        """
        self.listbox.delete ( 0, END )

TCC home: TCC home
NMT home: NMT home

Last updated: 2014-10-31 03:54 MDT