thantkguihighget.py :  » Business-Application » ThanCad » thancad-0.0.9 » thantkgui » 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 » thantkguihighget.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 interaction in a drawing
window.
"""

import time
from math import pi,sqrt,atan2,hypot
import p_gtkwid, tkSimpleDialog

from thandr import ThanText,ThanPoint
from thantrans import T
from thantkguilowget.thantkconst import *
from thanvar import Canc,ThanScheduler
from thanopt import thancadconf


class ThanTkGuiHighGet:
    "Mixin for highlevel getting information from Tk window."

    def __init__ (self):
        "Initialisation is needed."
        self.thanNest = False
  self.BSEL = 8
  self.BOSN = 15
  self.thanSelems = set()             # Elements which may be snapped to
  self.__externalFilterFunc = None    # External filter for the selection routines


    def thanGudSetSelExternalFilter(self, func):
        "Sets external filter function."
  self.__externalFilterFunc = func    # External filter for the selection routines


    def thanWaitFor(self, mes, state, cc1=None, cc2=None, cc3=None, rr1=None, tt1=None):
        "Sets the appropriate state to gui AND command line, and waits for either result."
  dc = self.thanCanvas; cmd = self.thanCom
  while True:
            res, cargo = self.__WaitFor(mes, state, cc1, cc2, cc3, rr1, tt1)
      try:    nest1 = (res[:1] == "'")
      except: nest1 = False
      if not nest1: return res, cargo
            if self.thanNest:
                cmd.thanAppend("A nested command is currently being executed.\n"\
              "Please exit this nested command in order to begin a new one\n", "can")
          continue
      self.thanNest = True
      self.__cmdstate = cmd.__dict__.copy()
      self.__dcstate  = dc.__dict__.copy()
      self.__scheduler = self.thanScheduler
      self.thanScheduler = ThanScheduler()
      cmd.thanCleanup()                       # Cleanup saved answer in commandline
      dc.thanCleanup()                        # Cleanup gui
      cmd.thanAppend("Beginning nested command..\n", "mes")
      cmd.thanAppend("%s\n" % res[1:], "com")
      cmd.thanBeginCommandNest(res[1:])
      cmd.thanAppend("Resuming original command\n", "mes")
      cmd.thanCleanup()                       # Cleanup saved answer in commandline
      dc.thanCleanup()                        # Cleanup gui
      cmd.__dict__.update(self.__cmdstate)
      dc.__dict__.update(self.__dcstate)
      self.thanScheduler = self.__scheduler
      del self.__cmdstate, self.__dcstate, self.__scheduler
      self.thanNest = False


    __READYSTATES = frozenset((THAN_STATE_POINT, THAN_STATE_POINT1,
                         THAN_STATE_LINE, THAN_STATE_LINE2,
             THAN_STATE_RECTANGLE, THAN_STATE_RECTRATIO,
             THAN_STATE_MOVE, THAN_STATE_ROADP, THAN_STATE_ROADR,
             THAN_STATE_POLAR, THAN_STATE_CIRCLE, THAN_STATE_ARC,
           ))


    def __WaitFor(self, mes, state, cc1=None, cc2=None, cc3=None, rr1=None, tt1=None):
        "Sets the appropriate state to gui AND command line, and waits for either result."
        dc = self.thanCanvas; cmd = self.thanCom; ct = self.thanCt

        strdis = self.thanProj[1].thanUnits.strdis
        strang = self.thanProj[1].thanUnits.strang
        strcoo = self.thanProj[1].thanUnits.strcoo
        dc.thanPrepare(state, cc1, cc2, cc3, rr1, tt1)

        while True:
         cmd.thanPrompt(mes)
         cmd.thanPrepare(state, cc1, cc2, rr1, tt1)     # It only sets the state and the ratio
         for com1 in self.thanScriptComs:
             cmd.thanEnter(com1)
             break
         while dc.thanState != THAN_STATE_NONE and cmd.thanState != THAN_STATE_NONE: dc.update()

   if dc.thanState == THAN_STATE_NONE:            # Gui answered
      res, cargo = dc.thanLastResult              # Get gui result
      dc.thanCleanup()                            # Cleanup saved answer in gui
      cmd.thanCleanup()                           # Cleanup commandline
      if res == Canc: return res, cargo
      if res == -2: return res, cargo
      if res == "c": return "c", cargo
#            xx, yy = ct.local2Global(res[0], res[1])
      if state in self.__READYSTATES:
          cmd.thanCleanup("%s" % strcoo(res))
    cmd.thanLastPoint(res)                  # Save last point for relative coords
    return res, cargo
      elif state == THAN_STATE_SNAPELEM:
          cmd.thanCleanup(" ")
          return res, cargo
      elif state == THAN_STATE_TEXT:
          assert False, "Boy, I would like to see this bug :)"
      elif state == THAN_STATE_ZOOMDYNAMIC or state == THAN_STATE_PANDYNAMIC:
          return res, cargo
      else:
          assert False, "Unknown state "+str(state)
   else:                                          # Commandline answered
      res = cmd.thanLastResult                    # Get commandline result
      try:    nest1 = (res[:1] == "'")
      except: nest1 = False
      if nest1: return res, None

            cmd.thanCleanup()                           # Cleanup saved answer in commandline
      dc.thanCleanup()                            # Cleanup gui
      if res == Canc: return res, None
      print "__waitfor: cmd answered: type=", type(res), "  result=", res
      return res, None

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

    def thanGudCommandBegin(self, com):
        "Begins a new command, as if the user entered com via the keyboard."
  self.thanCom.thanEnter(com, tags="com")

    def thanGudCommandEnd(self, mes=None, mestype="can"):
        "Print optional message and reprompt."
  if mes != None: self.thanCom.thanAppend("%s\n" % mes, mestype)
  self.thanCom.thanPrompt()
        self.thanCom.thanWaitingInput = True

    def thanGudCommandCan(self, mes=None, mestype="can"):
        "Print (at least default) cancel message and reprompt."
  from thantkcmd import DEFCAN
  if mes == None: mes = DEFCAN
#  self.thanCom.thanCleanup(mes)
  self.thanCom.thanAppend("%s\n" % mes, mestype)
  self.thanCom.thanPrompt()
        self.thanCom.thanWaitingInput = True


    def thanPrt(self, mes, tag="info1"):
        "Print to the command window; this is info, warnings, error etc."
  self.thanCom.thanAppend("%s\n" % mes, tag)

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

    def __getPoint(self, stat1, statonce="", strict=True, options=(), state="", args=()):
        """Gets a point but allows for options which are returned with the first letter (in lower case).

  1. Read user response.
  2. If user cancelled, return Canc
  3. If it is point, return point.
  4. If it is one of the options, return the first letter of this option.
  5. If we reached here it is not a point and not one of the options. So:
  6. If strict==False, return the user response.
  7. Otherwise print error message, and go to step 1.
  8. statonce is a message that is printed only the first time that this
     function asks for input. If the function asks again for input (in
     case of error, statonce is not printed).
  """
  stat = statonce+stat1
  opts = [opt.strip().lower() for opt in options]
        nd = self.thanProj[1].thanVar["dimensionality"]
  while True:
            res, cargo = self.thanWaitFor(stat, state, *args)
      if res == Canc: return Canc, "o", None               # The user cancelled
      istext = True
      try: res+"x"
      except: istext = False
      if not istext:
          try: c2 = [float(res[i]) for i in xrange(nd)]
          except (IndexError, ValueError, TypeError): pass
          else: return c2, "v", cargo                      # Validated coordinates are returned
      res1 = str(res).strip().lower()
      n = len(res1)
      if n == 0:
          if "" in opts: return "", "o", None              # Option is returned
      else:
          for opt in opts:
              if res1 == opt[:n]: return opt[0], "o", None # Option is returned
      if not strict: return res, "t", cargo                # Text other than coordinates or options
      if len(opts) == 0: stat = T["Invalid Point. Try again.\n"]
      else:              stat = T["Invalid point or option. Try again.\n"]
      self.thanCom.thanAppend(stat, "can")
      stat = stat1


    def thanGudGetPoint(self, stat1, statonce="", options=()):
        "Gets a point from user with possible options."
        return self.__getPoint(stat1, statonce, strict=True, options=options,
      state=THAN_STATE_POINT)[0]

    def thanGudGetPointOr(self, stat1, statonce="", options=()):
        "Gets a point from user with possible options or any other text."
        return self.__getPoint(stat1, statonce, strict=False, options=options,
      state=THAN_STATE_POINT)

    def thanGudGetPoint1(self, stat1, statonce="", options=()):
        "Gets a point from user with possible options; use a different cursor."
        return self.__getPoint(stat1, statonce, strict=True, options=options,
      state=THAN_STATE_POINT1)[0]

    def thanGudGetLine(self, c1, stat, statonce="", options=()):
        "Gets a line from user  beginning at c1, with possible options."
        return self.__getPoint(stat, statonce, strict=True, options=options,
      state=THAN_STATE_LINE, args=(c1,))[0]

    def thanGudGetLine2(self, c1, c2, stat, statonce="", options=()):
        "Gets a line dragging 2 lines from user beginning at c1,c2 with possible options."
        return self.__getPoint(stat, statonce, strict=True, options=options,
      state=THAN_STATE_LINE2, args=(c1,c2))[0]


    def thanGudGetRoadP(self, c1, c2, c3, r2, stat, statonce="", options=()):
        "Gets a line/arc combination from user, with possible options."
        res, typres, cargo = self.__getPoint(stat, statonce, strict=True, options=options,
      state=THAN_STATE_ROADP, args=(c1, c2, c3, r2))
  return res, cargo


    def thanGudGetRoadR(self, c1, c2, c3, r2, stat, statonce="", options=()):
        "Gets a line/arc combination from user, with possible options."
  while True:
            res, typres, cargo = self.__getPoint(stat, statonce, strict=False, options=options,
          state=THAN_STATE_ROADR, args=(c1, c2, c3, r2))
      if typres == "v":                  # coordinates
          from thanvar import calcRoadNodeR
          delta = hypot(res[1]-c2[1], res[0]-c2[0])
                ro = calcRoadNodeR(c1[0], c1[1], c2[0], c2[1], c3[0], c3[1], delta)
    return ro.R
      if typres == "o": return res       # Option or Cancel
      try:
          r = float(res)
    if r > 0.0: return r
      except ValueError:
          pass
      if options: statonce = T["Invalid point, positive number or option. Try again.\n"]
      else:       statonce = T["Invalid point or positive number. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""


    def thanGudGetMovend(self, c1, stat, elems=None, direction=None, statonce="", options=()):
        "Gets a vector distance from user, while dragging some elements."
        if elems == None: self.thanGudSetSelClone()
        else:             self.thanGudSetDrag(elems)
        return self.__getPoint(stat, statonce, strict=True, options=options,
            state=THAN_STATE_MOVE, args=(c1,direction))[0]


    def thanGudGetImPoint(self, stat1, image=None, ptol=0, threshold=None, statonce="", options=()):
        """Get a point which is in image, or any image; return image too.

        If image==None all active images are searched.
  If ptol>0, (ptol is in local coordinates) then a rectangle +=dx, +=dy
  where dx=dy=ptol in world coordinates is searched.
  if threshold!=None then the point must be part of a curve in image.
  """
  strict = True
  while True:
            cw = self.__getPoint(stat1, statonce, strict=True, options=options,
          state=THAN_STATE_POINT)[0]
            first = None, cw                               # cw may be None
      try: 0.0+cw[0]+cw[1]
      except (IndexError, TypeError): return first   # An option, or anything but point if strict==True
      if image == None: images = self.thanImages.itervalues()
      else:             images = [image]
      rasterFound = False
      for image in images:
          for k in xrange(ptol+1):
        wk, _ = self.thanCt.local2GlobalRel(k, k)
              for dx in -wk,wk:
                  for dy in -wk,wk:
          cw1 = list(cw)
          cw1[0] += dx
          cw1[1] += dy
                            try: jx, iy = image.thanGetPixCoor(cw1)
                      except IndexError: continue
          if threshold == None: return image, cw1
          if image[jx, iy]: return image, cw1
          if not rasterFound:
              rasterFound = True
        first = image, cw1    # Nearest raster to thepoint the user clicked
          if rasterFound: continue
          rasterFound = True
      if not strict: return first  # We didn't find any curve; return the nearest point with image
      if rasterFound: statonce = T["No curve was found at point. Try Again.\n"]
      else: statonce = T["No raster image found at point. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""

    def thanGudGetPolar(self, cc, r, stat, statonce="", options=()):
        "Gets the angle between x-axis and a dragged line of length r beginning at cc."
        while True:
      res, typres, cargo = self.__getPoint(stat, statonce=statonce, strict=False,
          options=options, args=(cc,None,None,r), state=THAN_STATE_POLAR)
      if typres == "v":              # coordinates
          th = atan2(res[1]-cc[1], res[0]-cc[0])
    return th
      if typres == "o": return res   # Option or Cancel
      try: th = float(res)
      except ValueError: pass
      else: return self.thanProj[1].thanUnits.unit2rad(th)
      if options: statonce = T["Invalid point, angle or option. Try again.\n"]
      else:       statonce = T["Invalid point or angle. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""

    def thanGudGetCircle(self, cc, stat, statonce="", options=()):
        "Gets a circle from user, centered at cc."
        while True:
            res, typres, cargo = self.__getPoint(stat, statonce=statonce, strict=False,
          options=options, args=(cc,), state=THAN_STATE_CIRCLE)
      if typres == "v":              # coordinates
          print "GUI answered"
          r = hypot(res[1]-cc[1], res[0]-cc[0])
          print "GUI answered: r=", r
    return r
      if typres == "o": return res   # Option or Cancel
      try:
          r = float(res)
          print "CMD answered: r=", r
    if r > 0.0: return r
      except ValueError:
          pass
      if options: statonce = T["Invalid point, positive number or option. Try again.\n"]
      else:       statonce = T["Invalid point or positive number. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""

    def thanGudGetArc(self, cc, r, theta1, stat, statonce="", options=()):
        "Gets a circlular arc from user, centered at cc, radius r and beginning at theta1."
        while True:
      res, typres, cargo = self.__getPoint(stat, statonce=statonce, strict=False,
          options=options, args=(cc,None,None,r,theta1), state=THAN_STATE_ARC)
      if typres == "v":              # coordinates
          th = atan2(res[1]-cc[1], res[0]-cc[0])
    return th
      if typres == "o": return res   # Option or Cancel
      try: th = float(res)
      except ValueError: pass
      else: return self.thanProj[1].thanUnits.unit2rad(th)
      if options: statonce = T["Invalid point, angle or option. Try again.\n"]
      else:       statonce = T["Invalid point or angle. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""

    def thanGudGetRect(self, c1, stat, statonce="", options=(), com=None):
        "Gets a rectangle from user, beginning at c1."
        return self.__getPoint(stat, statonce, strict=True, options=options,
      state=THAN_STATE_RECTANGLE, args=(c1, None, None, None, com))[0]

    def thanGudGetRectratio(self, c1, stat, ratio, statonce="", options=()):
        "Gets a rectangle from user, beginning at c1 with given ratio height/width."
        while True:
            res, typres, cargo = self.__getPoint(stat, statonce=statonce, strict=False,
          options=options, args=(c1,None,None,None,ratio), state=THAN_STATE_RECTRATIO)
      if typres == "v": return res   # coordinates
      if typres == "o": return res   # Option or Cancel
      try:
          r = float(res)
    if r != 0.0:
              cc = list(c1)
              cc[0] += r
              cc[1] += r*ratio
        return cc
      except ValueError:
          pass
      if options: statonce = T["Invalid point, nonzero number or option. Try again.\n"]
      else:       statonce = T["Invalid point or nonzero number. Try again.\n"]
      self.thanCom.thanAppend(statonce, "can")
      statonce = ""

    def __getText(self, stat1, default=None, validate=None, statonce="",
        strict=True, options=(), fullopt=False, state=THAN_STATE_TEXT, args=()):
        """Gets a point but allows for options which are returned with the first letter (in lower case).

  1. Read user response.
  2. If user cancelled, return Canc
  3. If it is blank and blank is an option, then return blank.
  4. Otherwise if it is blank and there is a default value
     set the response equal to this default value.
  5. If the response (the real or the default) is equal to an option
     return the option.
  6. If we reached here we have a nontrivial response from the user
     which must be checked if it is legal.
  6. If there is not a validate function, the response is legal and return it.
  7. Otherwise call the validate function and if validation is ok,
     return the validated value.
  8. if validation is NOT ok, but strict==False, we dont't mind and so
     return the (illegal) response.
  9. Otherwise print error message, and go to step 1.
  10.statonce is a message that is printed only the first time that this
     function asks for input. If the function asks again for input (in
     case of error, statonce is not printed).
  """
  stat = statonce+stat1
  opts = [opt.strip().lower() for opt in options]
  while True:
            res, cargo = self.thanWaitFor(stat, state, *args)
      if res == Canc: return Canc, "o", None             # The user cancelled
      res1 = str(res).strip().lower()
      if res1 == "" and "" in opts: return "", "o", None # Response blank, and blank is an option
      if res1 == "" and default != None:
          res = default                                  # Use default value
          res1 = str(res).strip().lower()
      n = len(res1)
      if n == 0:                                         # Check for options
          if "" in opts: return "", "o", None
      else:
          for opt in opts:
              if res1 == opt[:n]:
                  if fullopt:  return opt,    "o", None
                  else:        return opt[0], "o", None
      if validate == None: return res, "t", cargo        # No validation
            val, stat = validate(res, stat1)
      if val != None: return val, "v", cargo             # Validation ok
      if not strict: return res, "t", cargo              # We don't mind failed validation
      self.thanCom.thanAppend(stat, "can")
      stat = stat1


    def thanGudGetText(self, stat1, default=None, statonce="", strict=True):
        return self.__getText(stat1, default, statonce=statonce, strict=strict)[0]


    def thanGudGetText0(self, stat1, default=None, statonce="", strict=True):
        "Gets nonblank text from user."
  def validate(res, stat1):
      if res.strip() != "": return res, None
      return None, T["Non blank text is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce, strict=strict)[0]

    def thanGudGetOpts(self, stat1, default=None, statonce="", fullopt=False, options=()):
        "Gets text from user which must be one of the options."
        def validate(res, stat1):
            return None, T["Invalid option. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce, strict=True,
            fullopt=fullopt, options=options)[0]

    def thanGudGetYesno(self, stat1, default=None, statonce="", strict=True):
        "Gets nonblank text from user."
        def validate(res, stat1):
            res = res.strip().lower()
            if res[:2] == "ye": return True, None
            if res[:2] == "no": return False, None
            return None, T["Yes or No is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce, strict=strict)[0]

    def thanGudGetFloat(self, stat1, default=None, statonce="", strict=True,
        options=(), state=THAN_STATE_TEXT, args=()):
        "Gets a float number from user."
  def validate(res, stat1):
      try:
          val = float(res)
    return val, None
      except ValueError:
          pass
      return None, T["A real number is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce,
      strict=strict, options=options, state=state, args=args)[0]

    def thanGudGetPosFloat(self, stat1, default=None, statonce="", strict=True,
        options=(), state=THAN_STATE_TEXT, args=()):
        "Gets a positive float number from user."
  def validate(res, stat1):
      try:
          val = float(res)
    if val > 0.0: return val, None
      except ValueError:
          pass
      return None, T["A positive real number is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce,
      strict=strict, options=options, state=state, args=args)[0]

    def thanGudGetFloat2(self, stat1, default=None, limits=(None, None), statonce="", strict=True):
        "Gets a float number from user within limits."
  def validate(res, stat1):
      try:
          val = float(res)
    if limits[0] == None and limits[1] == None: return val, None
    if limits[0] != None and val >= limits[0]: return val, None
    if limits[1] != None and val <= limits[1]: return val, None
          if limits[1] <= val <= limits[1]: return val, None
    return None, T["Real number out of range. Try again.\n"]
      except ValueError:
          pass
      return None, T["A real number is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce, strict=strict)[0]

    def thanGudGetInt2(self, stat1, default=None, limits=(None, None), statonce="", strict=True):
        "Gets an integer number from user within limits."
  def validate(res, stat1):
      try:
          val = int(res)
    if limits[0] == None and limits[1] == None: return val, None
    if limits[0] != None and val >= limits[0]: return val, None
    if limits[1] != None and val <= limits[1]: return val, None
          if limits[1] <= val <= limits[1]: return val, None
    return None, T["Integer number out of range. Try again.\n"]
      except ValueError:
          pass
      return None, T["An integer number is required. Try again.\n"]
        return self.__getText(stat1, default, validate, statonce=statonce, strict=strict)[0]

    def thanGudGetSnapElem(self, stat1, default=None, statonce="", strict=True, options=()):
        "Gets a point from user with possible options."
  def validate(res, stat1):
      "Do not validate anything."
      try: res.thanTkGet
      except: pass
      else: return res, None
      return None, T["Invalid selection or option. Try again.\n"]
  otypes = thancadconf.thanOsnapModes
  otypes1 = otypes.copy()
  otypes.clear()
  otypes["ena"] = otypes["ele"] = True
        self.thanCanvas.thanChs.thanPush(4)                   # Save previous croshair; set rectangle croshair
        res = self.__getText(stat1, default, validate, statonce, strict, options,
      state=THAN_STATE_SNAPELEM)[0]
  otypes.clear()
  otypes.update(otypes1)
  self.thanCanvas.thanChs.thanPop()                     # Restore previous croshair
  return res

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

    def thanGudGetLayerleaf(self, mes):
        "Let the user select a single layer (only leaf layers)."
  proj = self.thanProj
  lt = proj[1].thanLayerTree
  lays = dict((lay.thanGetPathname(), lay) for lay in lt.dilay.itervalues())
  names = lays.keys()
  names.sort()
  win = p_gtkwid.ThanPoplist(self, names, width=50, title=mes)
  self.thanTkSetFocus()
  if win.result == None: return Canc
  return lays[win.result]

    def thanGudGetLayerleafs(self, mes):
        "Let the user select multiple layers (only leaf layers)."
  proj = self.thanProj
  lt = proj[1].thanLayerTree
  lays = dict((lay.thanGetPathname(), lay) for lay in lt.dilay.itervalues())
  names = lays.keys()
  names.sort()
  import Tkinter
  win = p_gtkwid.ThanPoplist(self, names, width=50, selectmode=Tkinter.EXTENDED, title=mes)
  self.thanTkSetFocus()
  if win.result == None: return Canc
  return [lays[n] for n in win.result]


    def thanGudGetText1(self, mes, textDefault):
        "Accepts a nonblank text via a modal window."
        from p_ggen import thanUnicode,thanUnunicode

        self.update_idletasks()     # Experience showed that there should be no pending
                                    # Tk jobs when we show a modal window.
                                    # _idletasks breaks WinDoze (98?) support. Skotistika
        while True:
            ans = tkSimpleDialog.askstring("Please enter text", mes,
                initialvalue=thanUnicode(textDefault), parent=self)
            if ans == None: return Canc
            if ans != "": return thanUnunicode(ans)
            self.bell()


    def thanGudGetFloat1(self, mes, textDefault):
        "Accepts a real number via a modal window."
        self.update_idletasks()     # Experience showed that there should be no pending
                              # Tk jobs when we show a modal window
            # _idletasks breaks WinDoze (98?) support. Skotistika
        ans = tkSimpleDialog.askfloat("Please enter a number", mes,
      initialvalue=str(textDefault), parent=self)
  return ans

    def thanGudGetPosFloat1(self, mes, textDefault):
        "Accepts a poistive real number via a modal window."
  ans = tkSimpleDialog.askfloat("Please enter a positive number", mes,
      initialvalue=str(textDefault), minvalue=0.00000001, parent=self)
  return ans


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

    def thanGudGetSel1(self, xa, ya):
        "Finds 1 element near xa, ya."
        ct = self.thanCt
        xa, ya = ct.global2Local(xa, ya)
        dc = self.thanCanvas
        bpix, hpix =  self.BSEL/2, self.BSEL/2
        self.thanProj[2].thanCanvas.thanCh.thanDisable()
        items = list(dc.find_overlapping(xa-bpix, ya-hpix, xa+bpix, ya+hpix))
        items.reverse()    # Tkinter places the most recently drawn element to the end of the list
                           # and the last element is probably the one we want to edit. It is also above the
                           # previous elements if the coincide
        tagel = self.thanProj[1].thanTagel
        for item in items:
            if dc.type(item) == "image": continue
#            if dc.type(item) == "polygon": continue
            print "thanGudGetSel1: type=", dc.type(item)
            if self.__externalFilterFunc == None: break
            titem = dc.gettags(item)[0]
            e = tagel[titem]
            if self.__externalFilterFunc(e): break  # If element satisfies the external filter OK
        else:
            self.thanProj[2].thanCanvas.thanCh.thanEnable()
            return 0, 0              # No element found near xa,ya
#        self.thanGudSetSelClear()
        dc.dtag("selall", "sel")                     # Clear tag "sel"
        dc.addtag_withtag("sel", item)
        self.__filtercros()
        return self.__selCount()


    def thanGudGetSelWin(self, xa, ya, xb, yb):
        "Gets a selection on a given window."
        ct = self.thanCt
        xa, ya = ct.global2Local(xa, ya)
        xb, yb = ct.global2Local(xb, yb)
        dc = self.thanCanvas
#        self.thanGudSetSelClear()
        dc.dtag("selall", "sel")                     # Clear tag "sel"
  self.thanProj[2].thanCanvas.thanCh.thanDisable()
        items = dc.addtag_enclosed("sel", xa, ya, xb, yb)
#       No need to avoid selecting the raster of ThanImage, because all the raster must be enclosed, in order to be selected
  print "filterwin started"; t1 = time.time()
  self.__filterwin()
  print "filterwin ended:", time.time()-t1
  return self.__selCount()

    def __selCount(self):
        "Updates and counts the selected ThanCad elements."
#        cget = self.thanCanvas.itemcget
        cget = self.thanCanvas.gettags
  tagel = self.thanProj[1].thanTagel
  self.thanSel = set(tagel[cget(item)[0]] for item in self.thanCanvas.find_withtag("sel"))
        nselect = len(self.thanSel)
  nduplic = nselect - len(self.thanSel - self.thanSelall)
  self.thanSelall |= self.thanSel
  self.thanProj[2].thanCanvas.thanCh.thanEnable()
  return nselect, nduplic

    def thanGudGetSelOld(self):
        "Updates and counts the selected ThanCad elements."
        dc = self.thanCanvas
        dc.dtag("selall", "sel")                     # Clear tag "sel"
  dc.addtag_withtag("sel", "selold")  # Add sel to all previously selected items
  dc.addtag_withtag("selall", "sel")  # Add selall to all selected items
  self.thanSel = self.thanSelold
        nselect = len(self.thanSel)
  nduplic = nselect - len(self.thanSel - self.thanSelall)
  self.thanSelall |= self.thanSel
  return nselect, nduplic

    def __filterwinold(self):
        """Discards 'compound' items that are not completely within the window.

        Some of ThanCad's elements, for now points and texts (and all the
        elements with dashed lines in the future), are represented by more
        than one Tkinter items. In select window, we must make sure that all
        the items of a single compound element are present within the window.
        If they are not, the element and its correspondig items are deleted
        from the selection.
        """
        dc = self.thanCanvas
        dc.addtag_withtag("sel1", "sel")  # Add sel1 to all items within selection window
#        print "elements selected=", dc.find_withtag("sel1")
#        print "noncompound elements=", dc.find_withtag("nocomp")
        dc.dtag("nocomp", "sel1")              # Delete sel1 from items of non-compound elements
        items = set(dc.find_withtag("sel1"))   # All items of compound elements within selection window
#        print "Items compound=", items
        while len(items) > 0:
            for item in items: break
#            titem = dc.itemcget(item, "tags").split()[0]
            titem = dc.gettags(item)[0]
            items1 = set(dc.find_withtag(titem)) # These are the items of a single ThanCad (compound) element
            if not items1 <= items:              # If items1 is not subset of items, then the ThanCad element..
                dc.dtag(titem, "sel")            # .. is removed from selection
            items -= items1
#            items.difference_update(items1)
        dc.dtag("all", "sel1")
        if self.__externalFilterFunc != None: self.__filterexternal()
        dc.addtag_withtag("selall", "sel")  # Add selall to all selected items


    def __filterwin(self):
        """Discards 'compound' items that are not completely within the window.

        Some of ThanCad's elements, for now points and texts (and all the
        elements with dashed lines in the future), are represented by more
        than one Tkinter items. In select window, we must make sure that all
        the items of a single compound element are present within the window.
        If they are not, the element and its correspondig items are deleted
        from the selection.
        """
        dc = self.thanCanvas
        items1 = {}
        for item in dc.find_all():
            titem = dc.gettags(item)[0]
            try: items1[titem].add(item)     # These are the items of a single ThanCad (compound) element
            except KeyError: items1[titem] = set((item,))

        dc.addtag_withtag("sel1", "sel")     # Add sel1 to all items within selection window
        dc.dtag("nocomp", "sel1")            # Delete sel1 from items of non-compound elements
        items = set(dc.find_withtag("sel1")) # All items of compound elements within selection window
        while len(items) > 0:
            for item in items: break
            titem = dc.gettags(item)[0]
            items2 = items1[titem]           # I use this instead of items2=dc.find_withtag(titem), because it is 30 times faster
            if not items2 <= items:          # If items1 is not subset of items, then the ThanCad element..
                dc.dtag(titem, "sel")        # .. is removed from selection
            items -= items2
        dc.dtag("all", "sel1")
        if self.__externalFilterFunc != None: self.__filterexternal()
        dc.addtag_withtag("selall", "sel")   # Add selall to all selected items


    def __filterexternal(self):
        "Removes elements that do not satisfy external filter."
        dc = self.thanCanvas
        items = set(dc.find_withtag("sel"))  # Find all geometricall selected items
        tagel = self.thanProj[1].thanTagel
        while len(items) > 0:
            for item in items: break
            titem = dc.gettags(item)[0]
            items1 = set(dc.find_withtag(titem)) # These are the items of a single ThanCad (compound) element
            e = tagel[titem]
            if not self.__externalFilterFunc(e):  # If element does not satisfy the external filter it..
                dc.dtag(titem, "sel")             # .. is removed from selection
            items -= items1


    def thanGudGetSelCros(self, xa, ya, xb, yb):
        "Gets a selection on a given crossing window."
        ct = self.thanCt
        xa, ya = ct.global2Local(xa, ya)
        xb, yb = ct.global2Local(xb, yb)
        dc = self.thanCanvas
#        self.thanGudSetSelClear()
        dc.dtag("selall", "sel")                     # Clear tag "sel"
  self.thanProj[2].thanCanvas.thanCh.thanDisable()
        dc.addtag_overlapping("sel", xa, ya, xb, yb)
#       We need to avoid selecting the raster of ThanImage
  print "filtercros started"; t1 = time.time()
  self.__filtercros()
  print "filtercros ended:", time.time()-t1
  return self.__selCount()


    def __filtercrosold(self):
        """Ensures that 'compound' items partialy within the window, are completely selected.

        Some of ThanCad's elements, for now points and texts (and all the
        elements with dashed lines in the future), are represented by more
        than one Tkinter items. In select crossing, we must make sure that if
        one of the items of a single compound element are present within the
        window, then all must be selected. If not all selected, the nonselected
        items are forced into the selection.
        """
        dc = self.thanCanvas
        tagseen = set()
        dc.addtag_withtag("sel1", "sel")  # Add sel1 to all items within selection window
#        print "elements selected=", dc.find_withtag("sel1")
#        print "noncompound elements=", dc.find_withtag("nocomp")
        dc.dtag("nocomp", "sel1")         # Delete sel1 from items of non-compound elements
        items = dc.find_withtag("sel1")   # All items of compound elements within selection window
#        print "Items compound=", items
        for item in items:
            titem = dc.gettags(item)[0]
            if titem in tagseen: continue
            if dc.type(item) == "image": # Do not consider the raster of ThanImage; ..
                dc.dtag(item, "sel")     # ..it will be selected only if the bounding rectange is selected..
                continue                 # ..tagseen ensures that the bounding rectangle has not yet been seen
            tagseen.add(titem)
            dc.addtag_withtag("sel", titem)
        dc.dtag("all", "sel1")
        if self.__externalFilterFunc != None: self.__filterexternal()
        dc.addtag_withtag("selall", "sel")  # Add selall to all selected items


    def __filtercros(self):
        """Ensures that 'compound' items partialy within the window, are completely selected.

        Some of ThanCad's elements, for now points and texts (and all the
        elements with dashed lines in the future), are represented by more
        than one Tkinter items. In select crossing, we must make sure that if
        one of the items of a single compound element are present within the
        window, then all must be selected. If not all selected, the nonselected
        items are forced into the selection.
        """
        dc = self.thanCanvas
        items1 = {}
        for item in dc.find_all():
            titem = dc.gettags(item)[0]
            try: items1[titem].add(item)  # These are the items of a single ThanCad (compound) element
            except KeyError: items1[titem] = set((item,))
        items2add = []

        tagseen = set()
        dc.addtag_withtag("sel1", "sel")  # Add sel1 to all items within selection window
        dc.dtag("nocomp", "sel1")         # Delete sel1 from items of non-compound elements
        items = dc.find_withtag("sel1")   # All items of compound elements within selection window
        for item in items:
            titem = dc.gettags(item)[0]
            if titem in tagseen: continue
            if dc.type(item) == "image": # Do not consider the raster of ThanImage; ..
                dc.dtag(item, "sel")     # ..it will be selected only if the bounding rectange is selected..
                continue                 # ..tagseen ensures that the bounding rectangle has not yet been seen
            tagseen.add(titem)
#            dc.addtag_withtag("sel", titem)
            items2add.extend(items1[titem])
        for item in items2add: dc.addtag_withtag("sel", item)
#        dc.addtag_withtag("sel", items2add)   # A single addtag_withtag is 30 times faster than many
        dc.dtag("all", "sel1")
        if self.__externalFilterFunc != None: self.__filterexternal()
        dc.addtag_withtag("selall", "sel")  # Add selall to all selected items


    def thanGudGetSelLayers(self, lays):
        "Gets a selection on a given set of layers."
  dc = self.thanCanvas
        dc.dtag("selall", "sel")                     # Clear tag "sel"
  for lay in lays:
            dc.addtag_withtag("sel", lay.thanTag)
  dc.addtag_withtag("selall", "sel")  # Add selall to all selected items
  return self.__selCount()


    def prtags(self, stag="all"):
        "Print Item tags of all items with tag stag."
  dc = self.thanCanvas
        print "Item tags of all items with tag '"+stag+"'"
        for item in dc.find_withtag(stag):
      print item, ":", dc.gettags(item)


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.