thantkguilowget.py :  » Business-Application » ThanCad » thancad-0.0.9 » thantkgui » thantkguilowget » 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 » Business Application » ThanCad 
ThanCad » thancad 0.0.9 » thantkgui » thantkguilowget » thantkguilowget.py
##############################################################################
# ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
# 
# Copyright (c) 2001-2009 Thanasis Stamos,  August 23, 2009
# URL:     http://thancad.sourceforge.net
# e-mail:  cyberthanasis@excite.com
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details (www.gnu.org/licenses/gpl.html).
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##############################################################################

"""\
ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.

This module defines functionality necessary for user lowlevel interaction in
a drawing window.
"""


from math import atan2,pi,fabs,hypot
import Tkinter

from p_ggen import Struct
from thantkconst import *
from thanvar import Canc,thanLogTk,calcRoadNode,calcRoadNodeR,tkRoadNode,tkRoadNodeR,Win32
from thanopt import thancadconf
from thandefs.thanatt import ThanAttCol

_AVOIDTAG = frozenset(("e0", "edrag"))


class ThanTkGuiLowGet(Tkinter.Canvas):
    "Lowlevel input from a Tk canvas."

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

    def __init__(self, proj, *args, **kw):
        "Initialise base class and then this class."
        Tkinter.Canvas.__init__(self, proj[2], *args, **kw)
  self.__sb = proj[2].thanStatusBar
  self.BSEL = proj[2].BSEL

#-------Do some local initialisation

        self.__ncrossfirst = 0
        self.__nfirst = 0

#  dc = self.thanCanvas
  dc = self
  dc.bind("<Key>",             self.__onChar)     # This should be deleted, or at least redirected to thanCom
        dc.bind("<Double-Button-1>", self.__onDclick)
        dc.bind("<Button-1>",        self.__onClick)
        dc.bind("<Button-3>",        self.__onClickr)
        dc.bind("<Motion>",          self.__onMotion)
        dc.bind("<B1-Motion>",       self.__onMotionDrag)
        dc.bind("<ButtonRelease-1>", self.__onReleaseDrag)
  if Win32:
      dc.bind("<MouseWheel>",      self.__mouseWheel)
      proj[2].bind("<MouseWheel>", self.__mouseWheelp)   # Hack for Windows: Yeh, Windows "just works", no need for hacks
        else:
            dc.bind("<Button-4>",        self.__down_zoomin)
            dc.bind("<Button-5>",        self.__up_zoomout)

        if not Win32:
      self.bind("<Page_Up>",        self.thanPanpageup)
      self.bind("<Shift-Page_Up>",  self.__donothing)
         self.bind("<Page_Down>",      self.thanPanpagedown)
      self.bind("<Shift-Page_Down>",self.__donothing)
  self.bind("<Control-Up>",    self.thanPanpageup)
  self.bind("<Control-Down>",  self.thanPanpagedown)
  self.bind("<Control-Left>",  self.thanPanpageleft)
  self.bind("<Control-Right>", self.thanPanpageright)
  self.bind("<F7>", self.__sb.thanToggleCoord)

        self.thanState = self.thanStateDrag = THAN_STATE_NONE

        dc.update_idletasks()      # _idletasks breaks WinDoze (98?) support. Skotistika
        mx = dc.winfo_width() - 1
        my = dc.winfo_height() - 1
        self.thanXcu = dc.canvasx(mx / 2)
        self.thanYcu = dc.canvasy(my / 2)

        self.thanCrosHairs = [(CrosHair,), (CrosHairCros,60), (CrosHairCros,40),
                        (CrosHairCros,20), (CrosHairRect,), (CrosHairDummy,)]
        self.thanIcrosHair = [0]              # Set big croshair
  self.thanCh = CrosHair(dc)
  self.after(250, self.thanCh.resize)   # Give the Canvas a fourth of a second, to stabilise

  self.__osnap = Struct()
  self.__osnap.size = proj[2].BOSN      # size of osnap signs
  self.__osnap.types = thancadconf.thanOsnapModes

  self.__osnap.active = "ena" in self.__osnap.types
  self.__osnap.preempt = False
  self.__osnap.items = ()
  self.__osnap.tcol = ThanAttCol(thancadconf.thanColOsn).thanTk
  self.__osnap.selems = proj[2].thanSelems # Elements which may be snapped to.
  self.__osnap.selem = None                # Snapable element which is near cursor.

  self.__wheel = Struct()
  self.__wheel.preempt = False
  self.__wheel.idle = 0
  self.__wheel.task = None

#  The following is needed in case the user turns the mouse weel
#       just after the drawing is opened
  self.__x1 = self.__y1 = self.__x2 = self.__y2 = self.__r1 = self.__t1 = None
  self.thanEconoRaster = False     # Economise raster regens in zoom (wheel)

  self.thanFloatMenu = None

  self.thanProj = proj
  self.win = proj[2]

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

    def __mouseWheel(self, evt):
        "Mouse wheel up or down; for windows only."
  if evt.delta < 0: self.__up_zoomout(evt)
  else:             self.__up_zoomout(evt, fact=1.25)


    def __mouseWheelp(self, evt):
        "Mouse wheel up or down when triggered on the parent; for windows only."
  self.update_idletasks()                   # so that .winfo_xxx() works
        evt.x = evt.x_root - self.winfo_rootx()
        evt.y = evt.y_root - self.winfo_rooty()
  if evt.delta < 0: self.__up_zoomout(evt)
  else:             self.__up_zoomout(evt, fact=1.25)


    def __up_zoomout(self, evt, fact=0.8):
        "Mouse wheel up - zoom out."
  if self.__wheel.preempt:
      thanLogTk.warning("__up_zoomout called preemptively; returning immediately.")
      return
        self.__wheel.preemt = True
  if self.__wheel.idle == 0:
      self.__wheel.idle = 1
      self.__wheel.task = self.after(500, self.__wheelClear)
            self.__wheel.preemt = False
      return
        x = self.canvasx(evt.x); y = self.canvasy(evt.y)        # canvas units
  if self.__wheel.idle == 1:
      if self.thanState == THAN_STATE_ZOOMDYNAMIC: return #The user already zooms (RealTime)
      self.after_cancel(self.__wheel.task)
      self.thanCh.thanDisable()                           #Zoom is clearer without croshair
      if self.thanEconoRaster:
          for (item1,item2),im in self.win.thanImages.iteritems():
              self.delete(item2)         #  Delete Images (they can't be zoomed), but not rectangles
#            self.__prepareZoom(x, y)
      self.__wheel.idle = 2
  self.after_cancel(self.__wheel.task)
        self.scale(Tkinter.ALL, x, y, fact, fact)
  if self.__x1 != None:
      self.__x1 = x + (self.__x1-x)*fact
      self.__y1 = y + (self.__y1-y)*fact
  if self.__x2 != None:
      self.__x2 = x + (self.__x2-x)*fact
      self.__y2 = y + (self.__y2-y)*fact
  if self.__r1 != None:
      self.__r1 *= fact
        self.__notifyScale(x, y, 1.0/fact)

  self.__wheel.task = self.after(500, self.__notifyWheelEnd)
        self.__wheel.preemt = False


    def __notifyScale(self, xc, yc, fact):
        "Notify drawing that the zoom has changed."
#        self.__calcZoom()
        self.__resultCoor(xc, yc)
        w = self.win.thanDoZoomDyn(self.thanLastResult[0], fact)
        v = self.thanProj[1].viewPort
        v[:] = w
  if not self.thanEconoRaster:
            self.win.thanAutoRegen(regenImages=True)     # Regen images only if zoom realtime is finished


    def __wheelClear(self):
        "Clear attempt to use the wheel."
  self.__wheel.idle = 0


    def __notifyWheelEnd(self):
        "Notify drawing that the zoom has changed."
  self.thanCh.thanEnable()
  if self.thanEconoRaster:
            self.win.thanAutoRegen(regenImages=True)     # Regen images only if zoom realtime is finished
  self.__wheel.idle = 0


    def __down_zoomin(self, evt):
        "Mouse wheel down - zoom in."
  self.__up_zoomout(evt, fact=1.25)

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

    def thanPanpagedown (self, evt): return self.__panPage(evt,  0, -1)
    def thanPanpageleft (self, evt): return self.__panPage(evt, -1,  0)
    def thanPanpageright(self, evt): return self.__panPage(evt,  1,  0)
    def thanPanpageup   (self, evt): return self.__panPage(evt,  0,  1)
    def __donothing(self, evt): pass

    def __panPage(self, evt, ix, iy):
        "Page up,down,left,right."
        dx, dy = self.win.thanPanPage(ix, iy)
  if dx != 0.0 and dy != 0.0: return "break"
#  if self.__x1 != None:
#      self.__x1 += dx
#      self.__y1 += dy
#  if self.__x2 != None:
#      self.__x2 += dx
#      self.__y2 += dy
  return "break"

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

    def __onMotionDrag(self, event):
        "Well, here is what should be drawn each time mouse moves while it is pressed."

#-------If not dragging or user is not pressing mouse key, do nothing

        if self.thanStateDrag == THAN_STATE_NONE or \
           self.thanStateDrag == THAN_STATE_DRAG2BEGIN:
#      self.__onMotion(event)
      return

#-------Initial values

  dc = self
        x = dc.canvasx(event.x); y = dc.canvasy(event.y)                # canvas units
  cc = list(self.thanProj[1].thanVar["elevation"])
        cc[:2] = self.win.thanCt.local2Global(x, y)  # User coordinates (transformed from canvas coordinates)
        self.__sb.thanCoorMouse(cc)

#-------The first drag must be at least 3 points (the user accidentally dragged!)

  if self.thanStateDrag == THAN_STATE_DRAGFIRST:
      if abs(x-self.__x2) < 3 and abs(y-self.__y2) < 3: return
            self.__prepareZoom(x, y)

            self.thanCh.thanDisable()          #  Disable croshair (dragging is clearer)
      if self.thanState == THAN_STATE_ZOOMDYNAMIC:
          for (item1,item2),im in self.win.thanImages.iteritems():
              dc.delete(item2)         #  Delete Images (they can't be zoomed), but not rectangles

      self.thanStateDrag = THAN_STATE_DRAGGING

#-------The user is dragging now

  if self.thanState == THAN_STATE_PANDYNAMIC:
            dx = -int(x - self.thanXcu)                    # pixels
            dy = -int(y - self.thanYcu)                    # pixels
            dc.xview(Tkinter.SCROLL, dx, Tkinter.UNITS)
            dc.yview(Tkinter.SCROLL, dy, Tkinter.UNITS)
      x += dx     # Because the view window changed, local coords of elements (and croshair)
      y += dy     # did not change with these commands. Thus modify croshair coordinates,
                  # so that croshair remains at the same "view" position
  elif self.thanState == THAN_STATE_ZOOMDYNAMIC:
            dy = int(y - self.thanYcu)                     # pixels
      fact = 1.03, 1.03
      if dy < 0: fact = 0.97, 0.97
      args = (Tkinter.ALL,) + self.__zoomorigc + fact
            dc.scale(*args)

#-------Ending values

        self.thanXcu = x; self.thanYcu = y


    def __prepareZoom(self, x, y):
            "Makes sentinel elements to prepare for zoom computation."
      self.update_idletasks()                       # _idletasks breaks WinDoze (98?) support. Skotistika
      self.__xa = self.canvasx(0); self.__ya = self.canvasy(0)
      self.__zoomorigc = x, y                                            # canvas units
            self.__zooma = self.create_line(x-10000, y-10000, x-10001, y-10001)  # sentinel element
            self.__zoomb = self.create_line(x+10000, y+10000, x+10001, y+10001)  # sentinel element

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

    def __onReleaseDrag(self, event):
        "Well, here is what should be done after the end of dragging."
        if self.thanStateDrag == THAN_STATE_NONE: return
        if self.thanStateDrag == THAN_STATE_DRAGFIRST: return
  if self.thanStateDrag != THAN_STATE_DRAGGING:
      thanLogTk.warning("tklowget: onReleaseDrag was trigered before onClick: probably, the click was lost!")

#-------Initial values

#        dc = self.thanCanvas
  dc = self
        x = dc.canvasx(event.x); y = dc.canvasy(event.y)

  if self.thanState == THAN_STATE_PANDYNAMIC:
      dc.update_idletasks()                         # _idletasks breaks WinDoze (98?) support. Skotistika
            xa = dc.canvasx(0); ya = dc.canvasy(0)
      self.__resultCoorRel0(xa-self.__xa, ya-self.__ya)
      self.thanCh.thanEnable(x, y)                              # Enable, resize and redraw the croshair
      self.thanState = self.thanStateDrag = THAN_STATE_NONE

  elif self.thanState == THAN_STATE_ZOOMDYNAMIC:
            if self.__zooma == None:
          thanLogTk.warning("tklowget: Release drag event triggered for no reason!")
    return
            self.__calcZoom()
      self.thanCh.thanEnable(x, y)                              # Enable, resize and redraw the croshair
      self.thanState = self.thanStateDrag = THAN_STATE_NONE
  else:
      assert False, "Unknown drag state="+str(self.thanState)

#-------Ending values

        self.thanXcu = x; self.thanYcu = y

    def __resultCoorRel0(self, dxp, dyp):
        "Convert relative pixel coordiantes to user data units."
  self.thanLastResult = ([0.0]*self.thanProj[1].thanVar["dimensionality"], None)
        self.thanLastResult[0][:2] = self.win.thanCt.local2GlobalRel(dxp, dyp)

    def __resultCoor(self, xp, yp):
        "Convert relative pixel coordiantes to user data units."
  self.thanLastResult = (list(self.thanProj[1].thanVar["elevation"]), None)
        self.thanLastResult[0][:2] = self.win.thanCt.local2Global(xp, yp)

    def __calcZoom(self):
            "Computes the zoom factor using the sentinel elements."
      ca = self.coords(self.__zooma)
      cb = self.coords(self.__zoomb)
            self.__debugZoom(ca, cb)     # Only for debugging
#      self.thanLastResult = self.__zoomorigc + (20000.0 / (cb[0] - ca[0]), )
            self.__resultCoor(*self.__zoomorigc)
      self.thanLastResult = (self.thanLastResult[0], 20000.0 / (cb[0] - ca[0]))

    def __debugZoom(self, ca, cb):
            "Check that the center of zoom remained in place; code only for debug; not needed in production."
      cc = (ca[0]+cb[0])*0.5, (ca[1]+cb[1])*0.5
      cor = self.__zoomorigc
      if abs(cc[0]-cor[0])+abs(cc[1]-cor[1]) > 0.5:
          thanLogTk.warning("Zoom center should be: %f %f but is: %f %f \n     ca=%f %f\n     cb=%f %f"\
     % (self.__zoomorigc[0], self.__zoomorigc[1], cc[0], cc[1], ca[0], ca[1], cb[0], cb[1]))

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

    def __onMotion(self, event):
        "Well, here is what should be drawn each time mouse moves."

#-------Initial values

#        dc = self.thanCanvas
  self.__osnap.active = "ena" in self.__osnap.types
  dc = self
        x = dc.canvasx(event.x); y = dc.canvasy(event.y)

#-------Cross hair, status line

        self.thanCh.draw(x, y)
  cc = list(self.thanProj[1].thanVar["elevation"])
        cc[:2] = self.win.thanCt.local2Global(x, y)  # User coordinates (transformed from canvas coordinates)
        self.__sb.thanCoorMouse(cc)

#-------Move selected itmes with cursor

#        if self.thanState == THAN_STATE_MOVE:
#      ca = dc.coords(self.__zooma)
#      dx, dy = (x-10000)-ca[0], (y-10000)-ca[1]
#      dc.move("edrag", dx, dy)
        if self.thanState == THAN_STATE_MOVE:
      ca = dc.coords(self.__zooma)
      dx, dy = (x-10000)-ca[0], (y-10000)-ca[1]
      if self.__cc2 != None:
          disproj = dx*self.__cc2[0] - dy*self.__cc2[1]  # The move is (reverse y due to coordinate systems)..
    dx = disproj*self.__cc2[0]                     # ..to the direction unit vector..
    dy = -disproj*self.__cc2[1]                     # .. self.__x1, self.__y1
#                orthoxy(self, xa, ya, xb, yb):  call this instead
      dc.move("edrag", dx, dy)

#-------Draw dragged line

        elif self.thanState == THAN_STATE_LINE:
            if self.__nfirst:
                i1 = self.__dragged
                self.__dragged = dc.create_line(self.__x1, self.__y1, x, y, fill="blue")
                dc.delete(i1)
            else:
                self.__dragged = dc.create_line(self.__x1, self.__y1, x, y, fill="blue")
                self.__nfirst = 1

#-------Draw 2 dragged lines

        elif self.thanState == THAN_STATE_LINE2:
            if self.__nfirst:
                draggedp = self.__dragged
                self.__dragged = [dc.create_line(self.__x1, self.__y1, x, y, fill="blue"),
                      dc.create_line(self.__x2, self.__y2, x, y, fill="blue"),
         ]
                for i1 in draggedp: dc.delete(i1)
            else:
                self.__dragged = [dc.create_line(self.__x1, self.__y1, x, y, fill="blue"),
                      dc.create_line(self.__x2, self.__y2, x, y, fill="blue"),
         ]
                self.__nfirst = 1

#-------Draw dragged line of certain length. __r1 is the length

        elif self.thanState == THAN_STATE_POLAR:
      dx1 = x - self.__x1; dy1 = y - self.__y1
      r = hypot(dx1, dy1)
      if r == 0: x1 = x; y1 = y
      else: x1 = self.__x1 + dx1*self.__r1/r; y1 = self.__y1 + dy1*self.__r1/r
            if self.__nfirst:
                i1 = self.__dragged
                self.__dragged = dc.create_line(self.__x1, self.__y1, x1, y1, fill="blue")
                dc.delete(i1)
            else:
                self.__dragged = dc.create_line(self.__x1, self.__y1, x1, y1, fill="blue")
                self.__nfirst = 1

#-------Draw dragged circle

        elif self.thanState == THAN_STATE_CIRCLE:
      r = hypot(x-self.__x1, y-self.__y1)
            if self.__nfirst:
          i1 = self.__dragged
                self.__dragged = dc.create_oval(self.__x1-r, self.__y1+r, self.__x1+r, self.__y1-r,
                     outline = "blue")
                dc.delete(i1)
            else:
                self.__dragged = dc.create_arc(self.__x1-r, self.__y1-r, self.__x1+r, self.__y1+r,
                     outline = "blue")
                self.__nfirst = 1

#-------Draw dragged arc. __r1 is the radius and __t1 is theta1

        elif self.thanState == THAN_STATE_ARC+"10000":
      theta1 = self.__t1 / pi * 180
      theta2 = atan2(-(y-self.__y1), x-self.__x1) / pi * 180
      if self.__nfirst:
          i1 = self. __dragged
                self.__dragged = dc.create_arc(self.__x1-self.__r1, self.__y1+self.__r1,
        self.__x1+self.__r1, self.__y1-self.__r1,
                    start=theta1, extent=(theta2-theta1)% 360.0, style=Tkinter.ARC, outline = "blue")
                dc.delete(i1)
            else:
                self.__dragged = dc.create_arc(self.__x1-self.__r1, self.__y1+self.__r1,
        self.__x1+self.__r1, self.__y1-self.__r1,
                    start=theta1, extent=(theta2-theta1)%360.0, style=Tkinter.ARC, outline = "blue")
                self.__nfirst = 1

#-------Draw dragged arc. __r1 is the radius and __t1 is theta1

        elif self.thanState == THAN_STATE_ARC:
      theta1 = self.__t1 / pi * 180
      theta2 = atan2(-(y-self.__y1), x-self.__x1) / pi * 180
      if self.__nfirst:
          draggedp = self. __dragged
                self.__dragged = (dc.create_arc(self.__x1-self.__r1, self.__y1+self.__r1,
                      self.__x1+self.__r1, self.__y1-self.__r1,
                                  start=theta1, extent=(theta2-theta1)%360.0, style=Tkinter.ARC,
          outline = "blue"),
          dc.create_line(self.__x1, self.__y1, x, y, fill="blue"),
         )
                for i2 in draggedp: dc.delete(i2)
            else:
                self.__dragged = (dc.create_arc(self.__x1-self.__r1, self.__y1+self.__r1,
                      self.__x1+self.__r1, self.__y1-self.__r1,
                                  start=theta1, extent=(theta2-theta1)%360.0, style=Tkinter.ARC,
          outline = "blue"),
          dc.create_line(self.__x1, self.__y1, x, y, fill="blue"),
                     )
                self.__nfirst = 1

#-------Draw dragged rectangle. __t1 is the command

        elif self.thanState == THAN_STATE_RECTANGLE:
      out = "blue"; fil = "darkblue"
#      if   self.__t1 == "w": stip = fi = "blue"
      if self.__t1 == "c": out = "cyan"; fil = "darkcyan"
      elif self.__t1 == "cw" and x < self.__x1: out = "cyan"; fil = "darkcyan"
#      elif self.__t1 == "cw":
#          if x > self.__x1:  stip = fi = "blue"
#          else:              stip = fi = "cyan"    # stipple="gray25"
      elif self.__t1 == None: out = "blue"; fil = None
            if self.__nfirst:
          i1 = self.__dragged
                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x, y, outline=out, fill=fil, stipple="gray25")
#                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x, y, outline=out, fill=fil)
    dc.delete(i1)
#    if self.__t1 != None: dc.lower(self.__dragged)
            else:
                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x, y, outline=out, fill=fil, stipple="gray25")
#                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x, y, outline=out, fill=fil)
                self.__nfirst = 1
#    if self.__t1 != None: dc.lower(self.__dragged)

#-------Draw dragged rectangle with fixed signed __t1=height/width  (

        elif self.thanState == THAN_STATE_RECTRATIO:
      stip = "blue"
      dx = abs(x - self.__x1); dy = abs(y - self.__y1)
      if dx > dy: dy = dx*self.__t1
      else:       dx = dy/self.__t1
      x2 = self.__x1+dx; y2 = self.__y1-dy
            if self.__nfirst:
          i1 = self.__dragged
                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x2, y2, outline=stip)
    dc.delete(i1)
            else:
                self.__dragged = dc.create_rectangle(self.__x1, self.__y1, x2, y2, outline=stip)
                self.__nfirst = 1

        elif self.thanState == THAN_STATE_ROADP:
            if self.__nfirst:
          draggedp = self.__dragged
                self.__dragged, ct = tkRoadNode(self.__x1, self.__y1, self.__x2, self.__y2,
                         x, y, self.__r1, dc, fill="blue", tags=())
                for i2 in draggedp: dc.delete(i2)
            else:
                self.__dragged, ct = tkRoadNode(self.__x1, self.__y1, self.__x2, self.__y2,
                         x, y, self.__r1, dc, fill="blue", tags=())
                self.__nfirst = 1

        elif self.thanState == THAN_STATE_ROADR:
            if self.__nfirst:
          draggedp = self.__dragged
                self.__dragged, ct = tkRoadNodeR(self.__x1, self.__y1, self.__x2, self.__y2,
         self.__x3, self.__y3, x, y, dc, self.win.thanCt, fill="blue", tags=())
                for i2 in draggedp: dc.delete(i2)
            else:
                self.__dragged, ct = tkRoadNodeR(self.__x1, self.__y1, self.__x2, self.__y2,
         self.__x3, self.__y3, x, y, dc, self.win.thanCt, fill="blue", tags=())
                self.__nfirst = 1

#-------Ending values

        self.thanXcu = x
        self.thanYcu = y
  if self.thanState != THAN_STATE_NONE and self.__osnap.active:
      self.after(10, self.__osnapFind)


    def orthoxy(self, xa, ya, xb, yb):
        "Force the coordinates of the mouse parallel to a direction; usually ortho mode."
        if not self.__idirs: return xb, yb
  dx = xb - xa
  dy = yb - ya
  dis = 0.0
  for idir1 in self.__idirs:
      disproj = dx*idir1[0] - dy*idir1[1]   # The negative sign in y is due to local coordinate systems
      if disproj > dismax:
          dismax = disproj
    idirmax = idir1
  return xa + dismax*idirmax[0], -dismax*idirmax[1]

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

    def __osnapFind(self):
        "Finds end, mid, center etc near the mouse cursor."
  if self.__osnap.preempt:
      thanLogTk.error("tklowget: osnapFind: preemptive call. It shouldn't happen.")
      return
  self.__osnap.preempt = True
        dc = self
  tagel = self.thanProj[1].thanTagel
  ct = self.win.thanCt
        bpix, hpix = self.BSEL/2, self.BSEL/2
  x1, y1 = self.thanXcu-bpix, self.thanYcu-hpix
  x2, y2 = self.thanXcu+bpix, self.thanYcu+hpix
        items = dc.find_overlapping(x1, y1, x2, y2)
  otypes = self.__osnap.types

        ccu = list(self.thanProj[1].thanVar["elevation"])
        ccu[:2] = ct.local2Global(self.thanXcu, self.thanYcu)
  if "ele" in otypes:
      selems = self.__osnap.selems
      for item in items:
          tags = dc.gettags(item)
                                                # Tkinter may automatically add the tag 'current' in any element
            # so the next test (which should succeed) does not succeed.
            # Thus we have to check for "e0" AND "edrag"
          if len(tags) < 2: continue      # We avoid current (rubber line)
          if tags[0] in _AVOIDTAG: continue    # We avoid current compound element (we shouldn't really)
          e = tagel[tags[0]]
          if e in selems:
        self.delete("e0")
        self.__osnap.selem = e
        e1 = e.thanClone()
        e1.thanTags = ("e0",)
        than = self.thanProj[2].than
        col1 = than.outline
        than.outline = self.__osnap.tcol
        e1.thanTkDraw(than)
        dc.itemconfig("e0", width=5)
        than.outline = col1
                   self.__osnap.preempt = False
        return
      self.__osnap.selem = None
      self.delete("e0")
            self.__osnap.preempt = False
      return
  elif "int" in otypes:
            ps = self.__osnapint(dc, tagel, otypes, items, ccu, self.__cc1)
  else:
      ps = []
      for item in items:
#          tags = dc.itemcget(item, "tags").split()
          if dc.type(item) == "image": continue # Ignore Tk images; only the bounding rectangle counts
          tags = dc.gettags(item)
          if len(tags) < 2: continue      # We avoid current (rubber line)
          if tags[0] in _AVOIDTAG: continue    # We avoid current compound element (we shouldn't really)
          e = tagel[tags[0]]
          p = e.thanOsnap(self.thanProj, otypes, ccu, None, self.__cc1)
          if p != None:
        ps.append(p)
        if len(ps) > 2: break
        for item1 in self.__osnap.items: dc.delete(item1)
  if len(ps) < 1:
      self.__osnap.items = ()
      self.__osnap.preempt = False
      return
  p = min(ps)
  b, h = ct.global2LocalRel(p[0], p[0])
  if b > 10*self.BSEL:
      self.__osnap.items = ()
      self.__osnap.preempt = False
      return
  t = self.__osnap.type = p[1]
  cc = self.__osnap.cc = p[2]
        x, y = ct.global2Local(cc[0], cc[1])
  self.__osnap.x = x
  self.__osnap.y = y
  b = h = self.__osnap.size/2
  tcol = self.__osnap.tcol
  if t == "end":
            self.__osnap.items = \
      ( dc.create_rectangle(x-b, y-h, x+b, y+h, width=3, outline=tcol, fill=""),
      )
  elif t == "mid":
            self.__osnap.items = \
            ( dc.create_polygon(x-b, y-b, x+b, y-b, x, y+b, width=3, outline=tcol, fill=""),
      )
  elif t == "cen":
            self.__osnap.items = \
            ( dc.create_oval(x-b, y-b, x+b, y+b, width=3, outline=tcol, fill=""),
      )
  elif t == "nod":
            self.__osnap.items = \
            ( dc.create_oval(x-b, y-b, x+b, y+b, width=3, outline=tcol, fill=""),
              dc.create_line(x-b, y-b, x+b, y+b, width=2, fill=tcol),
              dc.create_line(x-b, y+b, x+b, y-b, width=2, fill=tcol),
      )
  elif t == "qua":
            self.__osnap.items = \
      ( dc.create_polygon(x-b,y, x,y+b, x+b,y, x,y-b, width=2, outline=tcol, fill=""),
      )
  elif t == "int":
            self.__osnap.items = \
            ( dc.create_line(x-b, y-b, x+b, y+b, width=2, fill=tcol),
              dc.create_line(x-b, y+b, x+b, y-b, width=2, fill=tcol),
      )
  elif t == "tan":
      bb = 0.8*b
            self.__osnap.items = \
            ( dc.create_oval(x-bb, y-bb, x+bb, y+bb, width=3, outline=tcol, fill=""),
        dc.create_line(x-b, y-b, x+b, y-b, width=2, fill=tcol),
      )
  elif t == "nea":
            self.__osnap.items = \
      ( dc.create_polygon(x-b, y-b, x+b, y+b, x-b, y+b, x+b, y-b, width=2, outline=tcol, fill=""),
      )
        elif t == "per":
            self.__osnap.items = \
            ( dc.create_line(x-b, y-b, x-b, y+b, x+b, y+b, width=3, fill=tcol),
              dc.create_line(x-b, y, x, y, x, y+b, width=2, fill=tcol),
            )
        self.__osnap.preempt = False

    def __osnapint(self, dc, tagel, otypes, items, xcu, ycu, cc1):
            "Finds int near the mouse cursor."
      ps = []
      it = iter(items)
      for item in it:                     # Search for first element of intersection
#          tags = dc.itemcget(item, "tags").split()
          tags = dc.gettags(item)
          if len(tags) < 2:   continue    # We avoid current (rubber line)
          if tags[0] in _AVOIDTAG: continue    # We avoid current compound element (we shouldn't really)
          e = tagel[tags[0]]
    break
      else: return ps
      etried = False
      for item in it:                     # Search for second element of intersection
#          tags = dc.itemcget(item, "tags").split()
          tags = dc.gettags(item)
          if len(tags) < 2:   continue    # We avoid current (rubber line)
          if tags[0] in _AVOIDTAG: continue    # We avoid current compound element (we shouldn't really)
    etried = True
          e2 = tagel[tags[0]]
          p = e.thanOsnap(self.thanProj, otypes, xcu, ycu, e2, x1, y1)
          if p != None: ps.append(p); break
    e = e2
      if etried: return ps
      p = e.thanOsnap(self.thanProj, otypes, xcu, ycu, None, x1, y1)
      if p != None: ps.append(p)
      return ps

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

    CLICKDEFSTATES = frozenset((THAN_STATE_LINE, THAN_STATE_LINE2, THAN_STATE_POLAR,
                                THAN_STATE_CIRCLE, THAN_STATE_ARC, THAN_STATE_RECTANGLE))

    def __onClick(self, event):
        "Well, here is what should be done when mouse clicks."
  dc = self
#        dc.focus_set()              # This is needed otherwise text controls gets characters?
        x = dc.canvasx(event.x); y = dc.canvasy(event.y)   # Click coordinates

  if self.thanStateDrag != THAN_STATE_NONE:          # Check for dragging
            if self.thanStateDrag == THAN_STATE_DRAG2BEGIN:
          self.__x2 = x
    self.__y2 = y
          self.thanStateDrag = THAN_STATE_DRAGFIRST
      return

  if self.__osnap.active and self.__osnap.items != (): # If object snap, change click coordinates
      x = self.__osnap.x           # Canvas coordinates
      y = self.__osnap.y           # Canvas coordinates
      cc = self.__osnap.cc    # User coordinates (from object snap)
  else:
      cc = list(self.thanProj[1].thanVar["elevation"])
            cc[:2] = self.win.thanCt.local2Global(x, y)  # User coordinates (transformed from canvas coordinates)

        self.__sb.thanCoorClick(cc)                      # Draw status text

        if self.thanState == THAN_STATE_POINT:           # The user defined a point
            self.thanLastResult = cc, None
            self.thanState = THAN_STATE_NONE

        elif self.thanState in self.CLICKDEFSTATES:      # The user defined a line, circle, arc, rectangle
      try:    self.__dragged[0]
      except: dc.delete(self.__dragged)
      else:   [dc.delete(i1) for i1 in self.__dragged]
      del self.__dragged
            self.thanLastResult = cc, None
            self.thanState = THAN_STATE_NONE

        elif self.thanState == THAN_STATE_MOVE:
#            dc.delete(self.__zooma)    # __zooma has the tag "edrag"
      dc.delete("edrag")
            self.thanLastResult = cc, None
            self.thanState = THAN_STATE_NONE

        elif self.thanState == THAN_STATE_RECTRATIO:
#      dx = abs(x - self.__x1); dy = abs(y - self.__y1)
#      if dx > dy: dy = dx*self.__t1
#      else:       dx = dy/self.__t1
#            self.__resultCoor(self.__x1+dx, self.__y1-dy)
      dx = fabs(cc[0] - self.__cc1[0])
      dy = fabs(cc[1] - self.__cc1[1])
      if dx > dy: dy = dx*self.__t1
      else:       dx = dy/self.__t1
      cc[0] = self.__cc1[0] + dx
      cc[1] = self.__cc1[1] + dy
            self.thanLastResult = cc, None
            self.thanState = THAN_STATE_NONE

        elif self.thanState in (THAN_STATE_ROADP, THAN_STATE_ROADR):
      if self.__nfirst:
          for i1 in self.__dragged: dc.delete(i1)
            self.thanLastResult = cc, None
            self.thanState = THAN_STATE_NONE

        elif self.thanState == THAN_STATE_SNAPELEM:
      self.thanLastResult = self.__osnap.selem, None
      self.delete("e0")
            self.thanState = THAN_STATE_NONE

        self.thanXcu = x; self.thanYcu = y

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

    def __onClickr(self, event):
        "Well, here is what should be done when right mouse clicks."

#-------Initial values

#        dc = self.thanCanvas
  dc = self
#        dc.focus_set()              # This is needed otherwise text controls gets characters
        x = dc.canvasx(event.x)
        y = dc.canvasy(event.y)

#-------Check for dragging

  if self.thanStateDrag != THAN_STATE_NONE:
      if self.thanState == THAN_STATE_ZOOMDYNAMIC:
          self.win.thanScheduler.thanSchedule(self.win.thanGudCommandBegin, "panrealtime")
    self.win.thanCom.thanOnCharEsc(event)     # Finish zoom dynamic
            elif self.thanState == THAN_STATE_PANDYNAMIC:
          self.win.thanScheduler.thanSchedule(self.win.thanGudCommandBegin, "zoomrealtime")
    self.win.thanCom.thanOnCharEsc(event)     # Finish pan dynamic

#-------Check for road:point

  elif self.thanState == THAN_STATE_ROADP:
      if self.__nfirst:
          for i1 in self.__dragged: dc.delete(i1)
            self. __resultCoor(x, y)
            self.thanLastResult = (self.thanLastResult[0], "r")
            self.thanState = THAN_STATE_NONE

#-------Check for road:radius

  elif self.thanState == THAN_STATE_ROADR:
      self.__onClick(event)                         # It is like if the user pressed left click

#-------Check for idle


  elif self.thanState == THAN_STATE_NONE:
            if self.thanFloatMenu != None and self.thanFloatMenu.winfo_ismapped():
          self.thanFloatMenu.unpost()
      self.thanFloatMenu = self.__createFloatMenu()
      self.thanFloatMenu.post(event.x_root, event.y_root)

    def __createFloatMenu(self):
        m = Tkinter.Menu(self, tearoff=False)
        fbeg = self.win.thanGudCommandBegin
  m.add_command(label="Repeat last command", command=lambda fbeg=fbeg: fbeg(""))
  m.add_command(label="Real time zoom",      command=lambda fbeg=fbeg: fbeg("zoomrealtime"))
  m.add_command(label="Real time pan",       command=lambda fbeg=fbeg: fbeg("panrealtime"))

#  m1 = Menu(m, tearoff=False)
#  m1.add_checkbutton(label="zoom  when window changes", variable=self.zoomWhenConf)
#  m1.add_checkbutton(label="regen when window changes", variable=self.regenWhenConf)
#  m1.add_separator()
#  m1.add_checkbutton(label="regen when zoom", variable=self.regenWhenZoom)
#  m1.add_checkbutton(label="regen when zoom all", variable=self.regenWhenZoomall)
#  m1.add_checkbutton(label="center when zoom", variable=self.centerWhenZoom)
#  m1.add_separator()
#  m1.add_checkbutton(label="show menu bar", variable=self.showMenubar)
#  m1.add_checkbutton(label="show tool bar", variable=self.showToolbar)

#  m.add_cascade(label="options", menu=m1)
        return m

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

    def __onDclick(self, event):
        "On double click change to the next available croshair."
        self.thanRotateCroshair(self.canvasx(event.x), self.canvasy(event.y))

    def thanRotateCroshair(self, x1=None, y1=None):
        "Changes the croshair."
  self.thanIcrosHair[-1] = (self.thanIcrosHair[-1] + 1) % len(self.thanCrosHairs)
  self.thanSetCroshair(self.thanIcrosHair[-1], x1, y1)

    def thanPushCroshair(self, i, x1=None, y1=None):
        "Change the cursor temporarily."
  i %= len(self.thanCrosHairs)
  self.thanIcrosHair.append(i)
  self.thanSetCroshair(self.thanIcrosHair[-1], x1, y1)

    def thanPopCroshair(self, x1=None, y1=None):
        "Change to the previous cursor."
  if len(self.thanIcrosHair) < 1: return
  del self.thanIcrosHair[-1]
  self.thanSetCroshair(self.thanIcrosHair[-1], x1, y1)

    def thanSetCroshair(self, i, x1=None, y1=None):
        "Set the croshair."
  i %= len(self.thanCrosHairs)
  if x1 == None:
      x1 = self.thanCh.thanX1p
      y1 = self.thanCh.thanY1p
  clas = self.thanCrosHairs[i][0]
  args = self.thanCrosHairs[i][1:]
  self.thanCh.thanDisable()
  self.thanCh = clas(self, *args)
  self.thanCh.resize(x1, y1)

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

    def __onChar(self, event):
        "Well, here is what should be done when user presses a key."
  thanLogTk.error("onChar(): Unexpected Canvas <key> event redirected to ThanCom.")
  self.win.thanTkSetFocus()
  self.win.thanCom.thanOnChar(event)

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

    def thanPrepare(self, state, cc1=None, cc2=None, cc3=None, r1=None, t1=None, idirs=()):
        "Sets the appropriate state and lets gui take on."
  ct = self.win.thanCt
  self.__x1, self.__y1 = None, None
  if cc1 != None: self.__x1, self.__y1 = ct.global2Local(cc1[0], cc1[1])    # Transform to local coordinates
  self.__x2, self.__y2 = None, None
  if cc2 != None: self.__x2, self.__y2 = ct.global2Local(cc2[0], cc2[1])    # Transform to local coordinates
  self.__x3, self.__y3 = None, None
  if cc3 != None: self.__x3, self.__y3 = ct.global2Local(cc3[0], cc3[1])    # Transform to local coordinates
        self.__r1, self.__t1 = r1, t1
  if r1 != None: self.__r1, r  = ct.global2LocalRel(r1, r1)  # Transform to local coordinates
  self.__cc1 = cc1
  self.__cc2 = cc2
  self.__cc3 = cc3
  self.__rr1 = r1
  dc = self

        if state > THAN_STATE_DRAGFOLLOWS:
            self.thanStateDrag = THAN_STATE_DRAG2BEGIN
  elif state == THAN_STATE_MOVE:
      self.__zooma = self.__zoomb = dc.create_line(self.__x1-10000, self.__y1-10000,\
          self.__x1-10001, self.__y1-10001, tags="edrag")  # sentinel element

#  self.win.thanStatusxy(self.thanXcu, self.thanYcu)
  self.__nfirst = 0
  self.thanState = state
  if state == THAN_STATE_POINT1: self.thanState = THAN_STATE_POINT
        dc.config(cursor=thanCursor.get(state, ""))

  if state == THAN_STATE_ROADR:
#           hopefully everything is set, and the following event will trigger __onMotion to do the drawing work
            ro = calcRoadNode(self.__x1, self.__y1, self.__x2, self.__y2, self.__x3, self.__y3, self.__r1)
            dc.event_generate("<Motion>", when="head", x=ro.pm.x, y=ro.pm.y, warp=1)  # Set mouse position to the middle of the circular curve
  elif state == THAN_STATE_ROADP and cc3 != None:
#           hopefully everything is set, and the following event will trigger __onMotion to do the drawing work
            dc.event_generate("<Motion>", when="head", x=self.__x3, y=self.__y3, warp=1)  # Set mouse position to the prveious c3 point


    def thanCleanup(self):
        "Cleanup after we got the gui result."
#  self.win.thanStatusxy(self.thanXcu, self.thanYcu)
  dc = self
        dc.config(cursor="")
        self.thanLastResult = Canc, None

        try: self.__dragged
  except: pass
  else:
      try:    self.__dragged[0]
      except: dc.delete(self.__dragged)
      else:   [dc.delete(i1) for i1 in self.__dragged]
      del self.__dragged
        try: self.__zooma
  except: pass
  else:
      dc.delete(self.__zooma)                             # delete sentinel
            dc.delete(self.__zoomb)                             # delete sentinel
            del self.__zooma, self.__zoomb

        dc.delete("edrag")                                      # In case the user issued MOVE command, but the commandline answered

  for item1 in self.__osnap.items: dc.delete(item1)
  self.__osnap.items = ()

        if self.thanFloatMenu != None and self.thanFloatMenu.winfo_ismapped():
      self.thanFloatMenu.unpost()

        self.thanState = self.thanStateDrag = THAN_STATE_NONE

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

    def thanGudIdle(self):
        "Returns true if not in the middle of a command."
        return self.thanState == THAN_STATE_NONE

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

    def thanTkClear(self):
        "Clears a window."
  dc = self
        dc.delete(Tkinter.ALL)                          # Clear window
        self.thanCh.resize()

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

    def thanGudCoorChanged(self):
        "System of canvas changed; redraw croshair."
        self.thanCh.resize()

    def destroy(self):
        "Deletes circular references."
        del self.__sb, self.win, self.thanProj
  Tkinter.Canvas.destroy(self)

    def __delete__(self):
        "Show that self is really deleted."
        print "thantklowget:", self, "has been freed."


#############################################################################
#############################################################################

class CrosHair(object):
    "Draws, moves, deletes and maintains a croshair in a canvas."

    def __init__(self, dc):
        "Initialise the croshair."
  self.thanDc = dc
  self.thanExists = 0
        self.thanX1p = None
  self.thanY1p = None
  self.thanOn = True
  self.resize()


    def destroy(self):
        "Break circular references."
  del self.thanDc


    def resize(self, x1=None, y1=None):
        "Recomputes the size of the croshair."
        dc = self.thanDc
        dc.update_idletasks()        # _idletasks breaks WinDoze (98?) support. Skotistika

        maxx = dc.winfo_width() - 1
        maxy = dc.winfo_height() - 1
  minx = 0
  miny = 0

  self.thanMinx = dc.canvasx(minx)
  self.thanMiny = dc.canvasy(miny)
  self.thanMaxx = dc.canvasx(maxx)
  self.thanMaxy = dc.canvasy(maxy)

        if self.thanExists:
#      self.thanX1p = dc.coords(self.thanCh1)[0]
#      self.thanY1p = dc.coords(self.thanCh2)[1]
            dc.delete(self.thanCh1)
            dc.delete(self.thanCh2)
      self.thanExists = 0

        if x1 == None: x1 = self.thanX1p; y1 = self.thanY1p
  if x1 < self.thanMinx or x1 > self.thanMaxx or \
     y1 < self.thanMiny or y1 > self.thanMaxy:
            x1 = self.thanMinx + (self.thanMaxx - self.thanMinx) / 2
            y1 = self.thanMiny + (self.thanMaxy - self.thanMiny) / 2
  self.draw(x1, y1)
  self.thanX1p = x1; self.thanY1p = y1


    def draw(self, x1, y1):
        "Draws a croshair and deletes previous croshair."
  if self.thanOn:
    dc = self.thanDc
          if self.thanExists:
#            dc.move(self.thanCh1, x1-self.thanX1p, 0)
#            dc.move(self.thanCh2, 0, y1-self.thanY1p)
            dc.coords(self.thanCh1, x1, self.thanMiny, x1, self.thanMaxy,)
            dc.coords(self.thanCh2, self.thanMinx, y1, self.thanMaxx, y1)
      dc.lift(self.thanCh1)
      dc.lift(self.thanCh2)
    else:
            self.thanCh1 = dc.create_line(x1, self.thanMiny, x1, self.thanMaxy, fill="red")
            self.thanCh2 = dc.create_line(self.thanMinx, y1, self.thanMaxx, y1, fill="green")
      self.thanExists = 1

        self.thanX1p = x1
  self.thanY1p = y1


    def delete(self):
        "Deletes the croshair from the canvas - if it exists."
        if self.thanExists:
      dc = self.thanDc
            dc.delete(self.thanCh1)
            dc.delete(self.thanCh2)
      self.thanExists = 0


    def thanEnable(self, x1=None, y1=None):
        "Enable the croshair."
  self.thanOn = True
  self.resize(x1, y1)


    def thanDisable(self):
        "Disable the croshair."
  self.thanOn = False
  self.delete()

#############################################################################
#############################################################################

class CrosHairRect(CrosHair):
    "Draws, moves, deletes and maintains a limited croshair in a canvas."

    def __init__(self, dc, size=None):
        "Take size as an argument."
  if size == None: size = dc.BSEL
        self.dx = self.dy = size/2
  CrosHair.__init__(self, dc)

    def draw(self, x1, y1):
        "Draws a croshair and deletes previous croshair."
  if self.thanOn:
    dc = self.thanDc
          if self.thanExists:
            dc.coords(self.thanCh1, x1-self.dx, y1-self.dy, x1+self.dx, y1+self.dy)
      dc.lift(self.thanCh1)
    else:
            self.thanCh1 = dc.create_rectangle(x1-self.dx, y1-self.dy, x1+self.dx, y1+self.dy, outline="red")
      self.thanCh2 = None
      self.thanExists = 1

        self.thanX1p = x1
  self.thanY1p = y1


#############################################################################
#############################################################################

class CrosHairCros(CrosHair):
    "Draws, moves, deletes and maintains a limited croshair in a canvas."

    def __init__(self, dc, size=40):
        "Take size as an argument."
        self.dx = self.dy = size
  CrosHair.__init__(self, dc)


    def draw(self, x1, y1):
        "Draws a croshair and deletes previous croshair."
  if self.thanOn:
    dc = self.thanDc
          if self.thanExists:
#            dc.move(self.thanCh1, x1-self.thanX1p, 0)
#            dc.move(self.thanCh2, 0, y1-self.thanY1p)
            dc.coords(self.thanCh1, x1, y1-self.dy, x1, y1+self.dy)
            dc.coords(self.thanCh2, x1-self.dx, y1, x1+self.dx, y1)
      dc.lift(self.thanCh1)
      dc.lift(self.thanCh2)
    else:
            self.thanCh1 = dc.create_line(x1, y1-self.dy, x1, y1+self.dy, fill="red")
            self.thanCh2 = dc.create_line(x1-self.dx, y1, x1+self.dx, y1, fill="green")
      self.thanExists = 1

        self.thanX1p = x1
  self.thanY1p = y1


#############################################################################
#############################################################################

class CrosHairDummy(CrosHair):
    "A croshair that does nothing."

    def draw(self, x1, y1):
        "Draws a croshair and deletes previous croshair."
  if self.thanOn:
          if self.thanExists:
      pass
    else:
            self.thanCh1 = None
            self.thanCh2 = None
      self.thanExists = 1

        self.thanX1p = x1
  self.thanY1p = y1


#############################################################################
#############################################################################

#MODULE LEVEL CODE. IT IS EXECUTED ONLY ONCE

if __name__ == "__main__":
    print __doc__
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.