Wbase.py :  » Language-Interface » ChinesePython » chinesepython2.1.3-0.4 » Mac » Tools » IDE » 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 » Language Interface » ChinesePython 
ChinesePython » chinesepython2.1.3 0.4 » Mac » Tools » IDE » Wbase.py
import Qd
import Win
import QuickDraw
import Evt
import string
from types import *
import sys

WidgetsError = "WidgetsError"

DEBUG = 0

class Widget:
  
  """Base class for all widgets."""
  
  _selectable = 0
  
  def __init__(self, possize):
    self._widgets = []
    self._widgetsdict = {}
    self._possize = possize
    self._bounds = None
    self._visible = 1
    self._enabled = 0
    self._selected = 0
    self._activated = 0
    self._callback = None
    self._parent = None
    self._parentwindow = None
    self._bindings = {}
    self._backcolor = None
  
  def show(self, onoff):
    self._visible = onoff
    for w in self._widgets:
      w.show(onoff)
    if self._parentwindow is not None and self._parentwindow.wid is not None:
      self.SetPort()
      if onoff:
        self.draw()
      else:
        Qd.EraseRect(self._bounds)
  
  def draw(self, visRgn = None):
    if self._visible:
      # draw your stuff here
      pass
  
  def getpossize(self):
    return self._possize
  
  def getbounds(self):
    return self._bounds
  
  def move(self, x, y = None):
    """absolute move"""
    if y == None:
      x, y = x
    if type(self._possize) <> TupleType:
      raise WidgetsError, "can't move widget with bounds function"
    l, t, r, b = self._possize
    self.resize(x, y, r, b)
  
  def rmove(self, x, y = None):
    """relative move"""
    if y == None:
      x, y = x
    if type(self._possize) <> TupleType:
      raise WidgetsError, "can't move widget with bounds function"
    l, t, r, b = self._possize
    self.resize(l + x, t + y, r, b)
    
  def resize(self, *args):
    if len(args) == 1:
      if type(args[0]) == FunctionType or type(args[0]) == MethodType:
        self._possize = args[0]
      else:
        apply(self.resize, args[0])
    elif len(args) == 2:
      self._possize = (0, 0) + args
    elif len(args) == 4:
      self._possize = args
    else:
      raise TypeError, "wrong number of arguments"
    self._calcbounds()
  
  def open(self):
    self._calcbounds()
  
  def close(self):
    del self._callback
    del self._possize
    del self._bindings
    del self._parent
    del self._parentwindow
  
  def bind(self, key, callback):
    """bind a key or an 'event' to a callback"""
    if callback:
      self._bindings[key] = callback
    elif self._bindings.has_key(key):
      del self._bindings[key]
  
  def adjust(self, oldbounds):
    self.SetPort()
    self.GetWindow().InvalWindowRect(oldbounds)
    self.GetWindow().InvalWindowRect(self._bounds)
  
  def _calcbounds(self):
    # calculate absolute bounds relative to the window origin from our
    # abstract _possize attribute, which is either a 4-tuple or a callable object
    oldbounds = self._bounds
    pl, pt, pr, pb = self._parent._bounds
    if callable(self._possize):
      # _possize is callable, let it figure it out by itself: it should return 
      # the bounds relative to our parent widget.
      width = pr - pl
      height = pb - pt
      self._bounds = Qd.OffsetRect(self._possize(width, height), pl, pt)
    else:
      # _possize must be a 4-tuple. This is where the algorithm by Peter Kriens and
      # Petr van Blokland kicks in. (*** Parts of this algorithm are applied for 
      # patents by Ericsson, Sweden ***)
      l, t, r, b = self._possize
      # depending on the values of l(eft), t(op), r(right) and b(ottom), 
      # they mean different things:
      if l < -1:
        # l is less than -1, this mean it measures from the *right* of it's parent
        l = pr + l
      else:
        # l is -1 or greater, this mean it measures from the *left* of it's parent
        l = pl + l
      if t < -1:
        # t is less than -1, this mean it measures from the *bottom* of it's parent
        t = pb + t
      else:
        # t is -1 or greater, this mean it measures from the *top* of it's parent
        t = pt + t
      if r > 1:
        # r is greater than 1, this means r is the *width* of the widget
        r = l + r
      else:
        # r is less than 1, this means it measures from the *right* of it's parent
        r = pr + r
      if b > 1:
        # b is greater than 1, this means b is the *height* of the widget
        b = t + b
      else:
        # b is less than 1, this means it measures from the *bottom* of it's parent
        b = pb + b
      self._bounds = (l, t, r, b)
    if oldbounds and oldbounds <> self._bounds:
      self.adjust(oldbounds)
    for w in self._widgets:
      w._calcbounds()
  
  def test(self, point):
    if Qd.PtInRect(point, self._bounds):
      return 1
  
  def click(self, point, modifiers):
    pass
  
  def findwidget(self, point, onlyenabled = 1):
    if self.test(point):
      for w in self._widgets:
        widget = w.findwidget(point)
        if widget is not None:
          return widget
      if self._enabled or not onlyenabled:
        return self
  
  def forall(self, methodname, *args):
    for w in self._widgets:
      rv = apply(w.forall, (methodname,) + args)
      if rv: 
        return rv
    if self._bindings.has_key("<" + methodname + ">"):
      callback = self._bindings["<" + methodname + ">"]
      rv = apply(callback, args)
      if rv: 
        return rv
    if hasattr(self, methodname):
      method = getattr(self, methodname)
      return apply(method, args)
  
  def forall_butself(self, methodname, *args):
    for w in self._widgets:
      rv = apply(w.forall, (methodname,) + args)
      if rv: 
        return rv
  
  def forall_frombottom(self, methodname, *args):
    if self._bindings.has_key("<" + methodname + ">"):
      callback = self._bindings["<" + methodname + ">"]
      rv = apply(callback, args)
      if rv: 
        return rv
    if hasattr(self, methodname):
      method = getattr(self, methodname)
      rv = apply(method, args)
      if rv: 
        return rv
    for w in self._widgets:
      rv = apply(w.forall_frombottom, (methodname,) + args)
      if rv: 
        return rv
  
  def _addwidget(self, key, widget):
    if widget in self._widgets:
      raise ValueError, "duplicate widget"
    if self._widgetsdict.has_key(key):
      self._removewidget(key)
    self._widgets.append(widget)
    self._widgetsdict[key] = widget
    widget._parent = self
    self._setparentwindow(widget)
    if self._parentwindow and self._parentwindow.wid:
      widget.forall_frombottom("open")
      self.GetWindow().InvalWindowRect(widget._bounds)
  
  def _setparentwindow(self, widget):
    widget._parentwindow = self._parentwindow
    for w in widget._widgets:
      self._setparentwindow(w)
  
  def _removewidget(self, key):
    if not self._widgetsdict.has_key(key):
      raise KeyError, "no widget with key " + `key`
    widget = self._widgetsdict[key]
    for k in widget._widgetsdict.keys():
      widget._removewidget(k)
    if self._parentwindow._currentwidget == widget:
      widget.select(0)
      self._parentwindow._currentwidget = None
    self.SetPort()
    self.GetWindow().InvalWindowRect(widget._bounds)
    widget.close()
    del self._widgetsdict[key]
    self._widgets.remove(widget)
  
  def __setattr__(self, attr, value):
    if type(value) == InstanceType and isinstance(value, Widget) and  \
        attr not in ("_currentwidget", "_lastrollover", 
        "_parent", "_parentwindow", "_defaultbutton"):
      if hasattr(self, attr):
        raise ValueError, "Can't replace existing attribute: " + attr
      self._addwidget(attr, value)
    self.__dict__[attr] = value
  
  def __delattr__(self, attr):
    if attr == "_widgetsdict":
      raise AttributeError, "cannot delete attribute _widgetsdict"
    if self._widgetsdict.has_key(attr):
      self._removewidget(attr)
      if self.__dict__.has_key(attr):
        del self.__dict__[attr]
    elif self.__dict__.has_key(attr):
      del self.__dict__[attr]
    else:
      raise AttributeError, attr
  
  def __setitem__(self, key, value):
    self._addwidget(key, value)
  
  def __getitem__(self, key):
    if not self._widgetsdict.has_key(key):
      raise KeyError, key
    return self._widgetsdict[key]
  
  def __delitem__(self, key):
    self._removewidget(key)
  
  def SetPort(self):
    self._parentwindow.SetPort()
    

  def GetWindow(self):
    return self._parentwindow.GetWindow()
    
  def __del__(self):
    if DEBUG:
      print "%s instance deleted" % self.__class__.__name__
  
  def _drawbounds(self):
    Qd.FrameRect(self._bounds)


class ClickableWidget(Widget):
  
  """Base class for clickable widgets. (note: self._enabled must be true to receive click events.)"""
  
  def click(self, point, modifiers):
    pass
  
  def enable(self, onoff):
    self._enabled = onoff
    self.SetPort()
    self.draw()
  
  def callback(self):
    if self._callback:
      return CallbackCall(self._callback, 1)
  

class SelectableWidget(ClickableWidget):

  """Base class for selectable widgets."""
  
  _selectable = 1
  
  def select(self, onoff, isclick = 0):
    if onoff == self._selected:
      return 1
    if self._bindings.has_key("<select>"):
      callback = self._bindings["<select>"]
      if callback(onoff):
        return 1
    self._selected = onoff
    if onoff:
      if self._parentwindow._currentwidget is not None:
        self._parentwindow._currentwidget.select(0)
      self._parentwindow._currentwidget = self
    else:
      self._parentwindow._currentwidget = None
  
  def key(self, char, event):
    pass
  
  def drawselframe(self, onoff):
    if not self._parentwindow._hasselframes:
      return
    thickrect = Qd.InsetRect(self._bounds, -3, -3)
    state = Qd.GetPenState()
    Qd.PenSize(2, 2)
    if onoff:
      Qd.PenPat(Qd.qd.black)
    else:
      Qd.PenPat(Qd.qd.white)
    Qd.FrameRect(thickrect)
    Qd.SetPenState(state)
  
  def adjust(self, oldbounds):
    self.SetPort()
    if self._selected:
      self.GetWindow().InvalWindowRect(Qd.InsetRect(oldbounds, -3, -3))
      self.GetWindow().InvalWindowRect(Qd.InsetRect(self._bounds, -3, -3))
    else:
      self.GetWindow().InvalWindowRect(oldbounds)
      self.GetWindow().InvalWindowRect(self._bounds)


class _Line(Widget):
  
  def __init__(self, possize, thickness = 1):
    Widget.__init__(self, possize)
    self._thickness = thickness
  
  def open(self):
    self._calcbounds()
    self.SetPort()
    self.draw()
  
  def draw(self, visRgn = None):
    if self._visible:
      Qd.PaintRect(self._bounds)
  
  def _drawbounds(self):
    pass

class HorizontalLine(_Line):
  
  def _calcbounds(self):
    Widget._calcbounds(self)
    l, t, r, b = self._bounds
    self._bounds = l, t, r, t + self._thickness

class VerticalLine(_Line):
  
  def _calcbounds(self):
    Widget._calcbounds(self)
    l, t, r, b = self._bounds
    self._bounds = l, t, l + self._thickness, b


class Frame(Widget):
  
  def __init__(self, possize, pattern = Qd.qd.black, color = (0, 0, 0)):
    Widget.__init__(self, possize)
    self._framepattern = pattern
    self._framecolor = color
  
  def setcolor(self, color):
    self._framecolor = color
    self.SetPort()
    self.draw()
  
  def setpattern(self, pattern):
    self._framepattern = pattern
    self.SetPort()
    self.draw()
    
  def draw(self, visRgn = None):
    if self._visible:
      penstate = Qd.GetPenState()
      Qd.PenPat(self._framepattern)
      Qd.RGBForeColor(self._framecolor)
      Qd.FrameRect(self._bounds)
      Qd.RGBForeColor((0, 0, 0))
      Qd.SetPenState(penstate)

def _darkencolor((r, g, b)):
  return 0.75 * r, 0.75 * g, 0.75 * b

class BevelBox(Widget):
  
  """'Platinum' beveled rectangle."""
  
  def __init__(self, possize, color = (0xe000, 0xe000, 0xe000)):
    Widget.__init__(self, possize)
    self._color = color
    self._darkercolor = _darkencolor(color)
  
  def setcolor(self, color):
    self._color = color
    self.SetPort()
    self.draw()
  
  def draw(self, visRgn = None):
    if self._visible:
      l, t, r, b = Qd.InsetRect(self._bounds, 1, 1)
      Qd.RGBForeColor(self._color)
      Qd.PaintRect((l, t, r, b))
      Qd.RGBForeColor(self._darkercolor)
      Qd.MoveTo(l, b)
      Qd.LineTo(r, b)
      Qd.LineTo(r, t)
      Qd.RGBForeColor((0, 0, 0))


class Group(Widget):
  
  """A container for subwidgets"""


class HorizontalPanes(Widget):
  
  """Panes, a.k.a. frames. Works a bit like a group. Devides the widget area into "panes",
  which can be resized by the user by clicking and dragging between the subwidgets."""
  
  _direction = 1
  
  def __init__(self, possize, panesizes = None, gutter = 8):
    """panesizes should be a tuple of numbers. The length of the tuple is the number of panes, 
    the items in the tuple are the relative sizes of these panes; these numbers should add up 
    to 1 (the total size of all panes)."""
    ClickableWidget.__init__(self, possize)
    self._panesizes = panesizes
    self._gutter = gutter
    self._enabled = 1
    self.setuppanes()
  
  #def open(self):
  #  self.installbounds()
  #  ClickableWidget.open(self)
  
  def _calcbounds(self):
    # hmmm. It should not neccesary be override _calcbounds :-(
    self.installbounds()
    Widget._calcbounds(self)
  
  def setuppanes(self):
    panesizes = self._panesizes
    total = 0
    if panesizes is not None:
      #if len(self._widgets) <> len(panesizes):
      #  raise TypeError, 'number of widgets does not match number of panes'
      for panesize in panesizes:
        if not 0 < panesize < 1:
          raise TypeError, 'pane sizes must be between 0 and 1, not including.'
        total = total + panesize
      if round(total, 4) <> 1.0:
        raise TypeError, 'pane sizes must add up to 1'
    else:
      # XXX does not work!
      step = 1.0 / len(self._widgets)
      panesizes = []
      for i in range(len(self._widgets)):
        panesizes.append(step)
    current = 0
    self._panesizes = []
    self._gutters = []
    for panesize in panesizes:
      if current:
        self._gutters.append(current)
      self._panesizes.append((current, current + panesize))
      current = current + panesize
    self.makepanebounds()
  
  def getpanesizes(self):
    return map(lambda (fr, to): to-fr,  self._panesizes)
  
  boundstemplate = "lambda width, height: (0, height * %s + %d, width, height * %s + %d)"
  
  def makepanebounds(self):
    halfgutter = self._gutter / 2
    self._panebounds = []
    for i in range(len(self._panesizes)):
      panestart, paneend = self._panesizes[i]
      boundsstring = self.boundstemplate % (`panestart`, panestart and halfgutter, 
              `paneend`, (paneend <> 1.0) and -halfgutter)
      self._panebounds.append(eval(boundsstring))
  
  def installbounds(self):
    #self.setuppanes()
    for i in range(len(self._widgets)):
      w = self._widgets[i]
      w._possize = self._panebounds[i]
      #if hasattr(w, "setuppanes"):
      #  w.setuppanes()
      if hasattr(w, "installbounds"):
        w.installbounds()
  
  def rollover(self, point, onoff):
    if onoff:
      orgmouse = point[self._direction]
      halfgutter = self._gutter / 2
      l, t, r, b = self._bounds
      if self._direction:
        begin, end = t, b
      else:
        begin, end = l, r
      
      i = self.findgutter(orgmouse, begin, end)
      if i is None:
        SetCursor("arrow")
      else:
        SetCursor(self._direction and 'vmover' or 'hmover')
  
  def findgutter(self, orgmouse, begin, end):
    tolerance = max(4, self._gutter) / 2
    for i in range(len(self._gutters)):
      pos = begin + (end - begin) * self._gutters[i]
      if abs(orgmouse - pos) <= tolerance:
        break
    else:
      return
    return i
  
  def click(self, point, modifiers):
    # what a mess...
    orgmouse = point[self._direction]
    halfgutter = self._gutter / 2
    l, t, r, b = self._bounds
    if self._direction:
      begin, end = t, b
    else:
      begin, end = l, r
    
    i = self.findgutter(orgmouse, begin, end)
    if i is None:
      return
    
    pos = orgpos = begin + (end - begin) * self._gutters[i]  # init pos too, for fast click on border, bug done by Petr
    
    minpos = self._panesizes[i][0]
    maxpos = self._panesizes[i+1][1]
    minpos = begin + (end - begin) * minpos + 64
    maxpos = begin + (end - begin) * maxpos - 64
    if minpos > orgpos and maxpos < orgpos:
      return
    
    #SetCursor("fist")
    self.SetPort()
    if self._direction:
      rect = l, orgpos - 1, r, orgpos
    else:
      rect = orgpos - 1, t, orgpos, b
    
    # track mouse --- XXX  move to separate method?
    Qd.PenMode(QuickDraw.srcXor)
    Qd.PenPat(Qd.qd.gray)
    Qd.PaintRect(rect)
    lastpos = None
    while Evt.Button():
      pos = orgpos - orgmouse + Evt.GetMouse()[self._direction]
      pos = max(pos, minpos)
      pos = min(pos, maxpos)
      if pos == lastpos:
        continue
      Qd.PenPat(Qd.qd.gray)
      Qd.PaintRect(rect)
      if self._direction:
        rect = l, pos - 1, r, pos
      else:
        rect = pos - 1, t, pos, b
      Qd.PenPat(Qd.qd.gray)
      Qd.PaintRect(rect)
      lastpos = pos
    Qd.PaintRect(rect)
    Qd.PenNormal()
    SetCursor("watch")
    
    newpos = (pos - begin) / float(end - begin)
    self._gutters[i] = newpos
    self._panesizes[i] = self._panesizes[i][0], newpos
    self._panesizes[i+1] = newpos, self._panesizes[i+1][1]
    self.makepanebounds()
    self.installbounds()
    self._calcbounds()
  

class VerticalPanes(HorizontalPanes):
  """see HorizontalPanes"""
  _direction = 0
  boundstemplate = "lambda width, height: (width * %s + %d, 0, width * %s + %d, height)"


class ColorPicker(ClickableWidget):
  
  """Color picker widget. Allows the user to choose a color."""
  
  def __init__(self, possize, color = (0, 0, 0), callback = None):
    ClickableWidget.__init__(self, possize)
    self._color = color
    self._callback = callback
    self._enabled = 1
  
  def click(self, point, modifiers):
    if not self._enabled:
      return
    import ColorPicker
    newcolor, ok = ColorPicker.GetColor("", self._color)
    if ok:
      self._color = newcolor
      self.SetPort()
      self.draw()
      if self._callback:
        return CallbackCall(self._callback, 0, self._color)
  
  def set(self, color):
    self._color = color
    self.SetPort()
    self.draw()
  
  def get(self):
    return self._color
  
  def draw(self, visRgn=None):
    if self._visible:
      if not visRgn:
        visRgn = self._parentwindow.wid.GetWindowPort().visRgn
      Qd.PenPat(Qd.qd.gray)
      rect = self._bounds
      Qd.FrameRect(rect)
      rect = Qd.InsetRect(rect, 3, 3)
      Qd.PenNormal()
      Qd.RGBForeColor(self._color)
      Qd.PaintRect(rect)
      Qd.RGBForeColor((0, 0, 0))
      

# misc utils

def CallbackCall(callback, mustfit, *args):
  """internal helper routine for W"""
  # XXX this function should die.
  if type(callback) == FunctionType:
    func = callback
    maxargs = func.func_code.co_argcount
  elif type(callback) == MethodType:
    func = callback.im_func
    maxargs = func.func_code.co_argcount - 1
  else:
    if callable(callback):
      return apply(callback, args)
    else:
      raise TypeError, "uncallable callback object"
  
  if func.func_defaults:
    minargs = maxargs - len(func.func_defaults)
  else:
    minargs = maxargs
  if minargs <= len(args) <= maxargs:
    return apply(callback, args)
  elif not mustfit and minargs == 0:
    return callback()
  else:
    if mustfit:
      raise TypeError, "callback accepts wrong number of arguments: " + `len(args)`
    else:
      raise TypeError, "callback accepts wrong number of arguments: 0 or " + `len(args)`


def HasBaseClass(obj, class_):
  try:
    raise obj
  except class_:
    return 1
  except:
    pass
  return 0


_cursors = {
  "watch"  : Qd.GetCursor(QuickDraw.watchCursor).data,
  "arrow"  : Qd.qd.arrow,
  "iBeam"  : Qd.GetCursor(QuickDraw.iBeamCursor).data,
  "cross"  : Qd.GetCursor(QuickDraw.crossCursor).data,
  "plus"    : Qd.GetCursor(QuickDraw.plusCursor).data,
  "hand"  : Qd.GetCursor(468).data,
  "fist"    : Qd.GetCursor(469).data,
  "hmover"  : Qd.GetCursor(470).data,
  "vmover"  : Qd.GetCursor(471).data,
  "zoomin"  : Qd.GetCursor(472).data,
  "zoomout"  : Qd.GetCursor(473).data,
  "zoom"  : Qd.GetCursor(474).data,
}

def SetCursor(what):
  """Set the cursorshape to any of these: 'arrow', 'cross', 'fist', 'hand', 'hmover', 'iBeam', 
  'plus', 'vmover', 'watch', 'zoom', 'zoomin', 'zoomout'."""
  Qd.SetCursor(_cursors[what])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.