PmwScrolledFrame.py :  » GUI » Pmw » Pmw.1.3.2 » src » Pmw » Pmw_1_3 » lib » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » Pmw 
Pmw » Pmw.1.3.2 » src » Pmw » Pmw_1_3 » lib » PmwScrolledFrame.py
import string
import types
import Tkinter
import Pmw

class ScrolledFrame(Pmw.MegaWidget):
    def __init__(self, parent = None, **kw):

  # Define the megawidget options.
  INITOPT = Pmw.INITOPT
  optiondefs = (
      ('borderframe',    1,            INITOPT),
      ('horizflex',      'fixed',      self._horizflex),
      ('horizfraction',  0.05,         INITOPT),
      ('hscrollmode',    'dynamic',    self._hscrollMode),
      ('labelmargin',    0,            INITOPT),
      ('labelpos',       None,         INITOPT),
      ('scrollmargin',   2,            INITOPT),
      ('usehullsize',    0,            INITOPT),
      ('vertflex',       'fixed',      self._vertflex),
      ('vertfraction',   0.05,         INITOPT),
      ('vscrollmode',    'dynamic',    self._vscrollMode),
  )
  self.defineoptions(kw, optiondefs)

  # Initialise the base class (after defining the options).
  Pmw.MegaWidget.__init__(self, parent)

  # Create the components.
  self.origInterior = Pmw.MegaWidget.interior(self)

  if self['usehullsize']:
      self.origInterior.grid_propagate(0)

  if self['borderframe']:
      # Create a frame widget to act as the border of the clipper. 
      self._borderframe = self.createcomponent('borderframe',
        (), None,
        Tkinter.Frame, (self.origInterior,),
        relief = 'sunken',
        borderwidth = 2,
      )
      self._borderframe.grid(row = 2, column = 2, sticky = 'news')

      # Create the clipping window.
      self._clipper = self.createcomponent('clipper',
        (), None,
        Tkinter.Frame, (self._borderframe,),
        width = 400,
        height = 300,
        highlightthickness = 0,
        borderwidth = 0,
      )
      self._clipper.pack(fill = 'both', expand = 1)
  else:
      # Create the clipping window.
      self._clipper = self.createcomponent('clipper',
        (), None,
        Tkinter.Frame, (self.origInterior,),
        width = 400,
        height = 300,
        relief = 'sunken',
        borderwidth = 2,
      )
      self._clipper.grid(row = 2, column = 2, sticky = 'news')

  self.origInterior.grid_rowconfigure(2, weight = 1, minsize = 0)
  self.origInterior.grid_columnconfigure(2, weight = 1, minsize = 0)
  
  # Create the horizontal scrollbar
  self._horizScrollbar = self.createcomponent('horizscrollbar',
    (), 'Scrollbar',
    Tkinter.Scrollbar, (self.origInterior,),
          orient='horizontal',
    command=self.xview
  )

  # Create the vertical scrollbar
  self._vertScrollbar = self.createcomponent('vertscrollbar',
    (), 'Scrollbar',
    Tkinter.Scrollbar, (self.origInterior,),
    orient='vertical',
    command=self.yview
  )

  self.createlabel(self.origInterior, childCols = 3, childRows = 3)

  # Initialise instance variables.
  self._horizScrollbarOn = 0
  self._vertScrollbarOn = 0
  self.scrollTimer = None
  self._scrollRecurse = 0
  self._horizScrollbarNeeded = 0
  self._vertScrollbarNeeded = 0
  self.startX = 0
  self.startY = 0
  self._flexoptions = ('fixed', 'expand', 'shrink', 'elastic')

  # Create a frame in the clipper to contain the widgets to be
  # scrolled.
  self._frame = self.createcomponent('frame',
    (), None,
    Tkinter.Frame, (self._clipper,)
  )

  # Whenever the clipping window or scrolled frame change size,
  # update the scrollbars.
  self._frame.bind('<Configure>', self._reposition)
  self._clipper.bind('<Configure>', self._reposition)

        # Work around a bug in Tk where the value returned by the
        # scrollbar get() method is (0.0, 0.0, 0.0, 0.0) rather than
        # the expected 2-tuple.  This occurs if xview() is called soon
        # after the Pmw.ScrolledFrame has been created.
        self._horizScrollbar.set(0.0, 1.0)
        self._vertScrollbar.set(0.0, 1.0)

  # Check keywords and initialise options.
  self.initialiseoptions()

    def destroy(self):
  if self.scrollTimer is not None:
      self.after_cancel(self.scrollTimer)
      self.scrollTimer = None
  Pmw.MegaWidget.destroy(self)

    # ======================================================================

    # Public methods.

    def interior(self):
  return self._frame

    # Set timer to call real reposition method, so that it is not
    # called multiple times when many things are reconfigured at the
    # same time.
    def reposition(self):
  if self.scrollTimer is None:
      self.scrollTimer = self.after_idle(self._scrollBothNow)

    # Called when the user clicks in the horizontal scrollbar. 
    # Calculates new position of frame then calls reposition() to
    # update the frame and the scrollbar.
    def xview(self, mode = None, value = None, units = None):

        if type(value) == types.StringType:
            value = string.atof(value)
        if mode is None:
            return self._horizScrollbar.get()
  elif mode == 'moveto':
      frameWidth = self._frame.winfo_reqwidth()
      self.startX = value * float(frameWidth)
  else: # mode == 'scroll'
      clipperWidth = self._clipper.winfo_width()
      if units == 'units':
    jump = int(clipperWidth * self['horizfraction'])
      else:
    jump = clipperWidth
            self.startX = self.startX + value * jump

  self.reposition()

    # Called when the user clicks in the vertical scrollbar. 
    # Calculates new position of frame then calls reposition() to
    # update the frame and the scrollbar.
    def yview(self, mode = None, value = None, units = None):

        if type(value) == types.StringType:
            value = string.atof(value)
        if mode is None:
            return self._vertScrollbar.get()
  elif mode == 'moveto':
      frameHeight = self._frame.winfo_reqheight()
      self.startY = value * float(frameHeight)
  else: # mode == 'scroll'
      clipperHeight = self._clipper.winfo_height()
      if units == 'units':
    jump = int(clipperHeight * self['vertfraction'])
      else:
    jump = clipperHeight
            self.startY = self.startY + value * jump

  self.reposition()

    # ======================================================================

    # Configuration methods.

    def _hscrollMode(self):
  # The horizontal scroll mode has been configured.

  mode = self['hscrollmode']

  if mode == 'static':
      if not self._horizScrollbarOn:
    self._toggleHorizScrollbar()
  elif mode == 'dynamic':
      if self._horizScrollbarNeeded != self._horizScrollbarOn:
    self._toggleHorizScrollbar()
  elif mode == 'none':
      if self._horizScrollbarOn:
    self._toggleHorizScrollbar()
  else:
      message = 'bad hscrollmode option "%s": should be static, dynamic, or none' % mode
      raise ValueError, message

    def _vscrollMode(self):
  # The vertical scroll mode has been configured.

  mode = self['vscrollmode']

  if mode == 'static':
      if not self._vertScrollbarOn:
    self._toggleVertScrollbar()
  elif mode == 'dynamic':
      if self._vertScrollbarNeeded != self._vertScrollbarOn:
    self._toggleVertScrollbar()
  elif mode == 'none':
      if self._vertScrollbarOn:
    self._toggleVertScrollbar()
  else:
      message = 'bad vscrollmode option "%s": should be static, dynamic, or none' % mode
      raise ValueError, message

    def _horizflex(self):
  # The horizontal flex mode has been configured.

  flex = self['horizflex']

  if flex not in self._flexoptions:
      message = 'bad horizflex option "%s": should be one of %s' % \
        (flex, str(self._flexoptions))
      raise ValueError, message

  self.reposition()

    def _vertflex(self):
  # The vertical flex mode has been configured.

  flex = self['vertflex']

  if flex not in self._flexoptions:
      message = 'bad vertflex option "%s": should be one of %s' % \
        (flex, str(self._flexoptions))
      raise ValueError, message

  self.reposition()

    # ======================================================================

    # Private methods.

    def _reposition(self, event):
  self.reposition()

    def _getxview(self):

  # Horizontal dimension.
  clipperWidth = self._clipper.winfo_width()
  frameWidth = self._frame.winfo_reqwidth()
  if frameWidth <= clipperWidth:
      # The scrolled frame is smaller than the clipping window.

      self.startX = 0
      endScrollX = 1.0

      if self['horizflex'] in ('expand', 'elastic'):
    relwidth = 1
      else:
    relwidth = ''
  else:
      # The scrolled frame is larger than the clipping window.

      if self['horizflex'] in ('shrink', 'elastic'):
    self.startX = 0
    endScrollX = 1.0
    relwidth = 1
      else:
    if self.startX + clipperWidth > frameWidth:
        self.startX = frameWidth - clipperWidth
        endScrollX = 1.0
    else:
        if self.startX < 0:
      self.startX = 0
        endScrollX = (self.startX + clipperWidth) / float(frameWidth)
    relwidth = ''

  # Position frame relative to clipper.
  self._frame.place(x = -self.startX, relwidth = relwidth)
  return (self.startX / float(frameWidth), endScrollX)

    def _getyview(self):

  # Vertical dimension.
  clipperHeight = self._clipper.winfo_height()
  frameHeight = self._frame.winfo_reqheight()
  if frameHeight <= clipperHeight:
      # The scrolled frame is smaller than the clipping window.

      self.startY = 0
      endScrollY = 1.0

      if self['vertflex'] in ('expand', 'elastic'):
    relheight = 1
      else:
    relheight = ''
  else:
      # The scrolled frame is larger than the clipping window.

      if self['vertflex'] in ('shrink', 'elastic'):
    self.startY = 0
    endScrollY = 1.0
    relheight = 1
      else:
    if self.startY + clipperHeight > frameHeight:
        self.startY = frameHeight - clipperHeight
        endScrollY = 1.0
    else:
        if self.startY < 0:
      self.startY = 0
        endScrollY = (self.startY + clipperHeight) / float(frameHeight)
    relheight = ''

  # Position frame relative to clipper.
  self._frame.place(y = -self.startY, relheight = relheight)
  return (self.startY / float(frameHeight), endScrollY)

    # According to the relative geometries of the frame and the
    # clipper, reposition the frame within the clipper and reset the
    # scrollbars.
    def _scrollBothNow(self):
  self.scrollTimer = None

        # Call update_idletasks to make sure that the containing frame
        # has been resized before we attempt to set the scrollbars. 
        # Otherwise the scrollbars may be mapped/unmapped continuously.
        self._scrollRecurse = self._scrollRecurse + 1
        self.update_idletasks()
        self._scrollRecurse = self._scrollRecurse - 1
        if self._scrollRecurse != 0:
            return

  xview = self._getxview()
  yview = self._getyview()
  self._horizScrollbar.set(xview[0], xview[1])
  self._vertScrollbar.set(yview[0], yview[1])

  self._horizScrollbarNeeded = (xview != (0.0, 1.0))
  self._vertScrollbarNeeded = (yview != (0.0, 1.0))

  # If both horizontal and vertical scrollmodes are dynamic and
  # currently only one scrollbar is mapped and both should be
  # toggled, then unmap the mapped scrollbar.  This prevents a
  # continuous mapping and unmapping of the scrollbars. 
  if (self['hscrollmode'] == self['vscrollmode'] == 'dynamic' and
    self._horizScrollbarNeeded != self._horizScrollbarOn and
    self._vertScrollbarNeeded != self._vertScrollbarOn and
    self._vertScrollbarOn != self._horizScrollbarOn):
      if self._horizScrollbarOn:
    self._toggleHorizScrollbar()
      else:
    self._toggleVertScrollbar()
      return

  if self['hscrollmode'] == 'dynamic':
      if self._horizScrollbarNeeded != self._horizScrollbarOn:
    self._toggleHorizScrollbar()

  if self['vscrollmode'] == 'dynamic':
      if self._vertScrollbarNeeded != self._vertScrollbarOn:
    self._toggleVertScrollbar()

    def _toggleHorizScrollbar(self):

  self._horizScrollbarOn = not self._horizScrollbarOn

  interior = self.origInterior
  if self._horizScrollbarOn:
      self._horizScrollbar.grid(row = 4, column = 2, sticky = 'news')
      interior.grid_rowconfigure(3, minsize = self['scrollmargin'])
  else:
      self._horizScrollbar.grid_forget()
      interior.grid_rowconfigure(3, minsize = 0)

    def _toggleVertScrollbar(self):

  self._vertScrollbarOn = not self._vertScrollbarOn

  interior = self.origInterior
  if self._vertScrollbarOn:
      self._vertScrollbar.grid(row = 2, column = 4, sticky = 'news')
      interior.grid_columnconfigure(3, minsize = self['scrollmargin'])
  else:
      self._vertScrollbar.grid_forget()
      interior.grid_columnconfigure(3, minsize = 0)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.