aboutsummaryrefslogtreecommitdiff
path: root/debian/zinc-python/usr
diff options
context:
space:
mode:
authorAchil2022-09-06 18:56:51 +0200
committerAchil2022-09-06 18:56:51 +0200
commit5bce61c04e589e368d534c4797711ac73c1e1f23 (patch)
tree299f2b64723a5c9697937f651cecf1416604baad /debian/zinc-python/usr
parentb60b3de318b4e621518681cc2824b4d9c605ae9e (diff)
downloadtkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.zip
tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.gz
tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.bz2
tkzinc-5bce61c04e589e368d534c4797711ac73c1e1f23.tar.xz
Daniel Etienne pre release for Bullseye
Diffstat (limited to 'debian/zinc-python/usr')
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/Zinc.py1597
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/__init__.py4
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/geometry.py410
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/graphics.py2351
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/pictorial.py766
-rwxr-xr-xdebian/zinc-python/usr/lib/python2.7/dist-packages/python_zinc-1.0.egg-info10
-rwxr-xr-xdebian/zinc-python/usr/share/doc/zinc-python/changelog.gzbin0 -> 24196 bytes
-rwxr-xr-xdebian/zinc-python/usr/share/doc/zinc-python/copyright20
-rwxr-xr-xdebian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/paper.gifbin0 -> 1529 bytes
-rwxr-xr-xdebian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/testGraphics.py1864
10 files changed, 7022 insertions, 0 deletions
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/Zinc.py b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/Zinc.py
new file mode 100755
index 0000000..d5a276d
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/Zinc.py
@@ -0,0 +1,1597 @@
+#!/usr/bin/python
+# -*- coding: iso-8859-1 -*-
+#
+# Zinc.py -- Python interface to the tkzinc widget.
+#
+# Authors : Frederic Lepied, Patrick Lecoanet
+# Created Date : Thu Jul 22 09:36:04 1999
+#
+# $Id: Zinc.py 1908 2008-09-15 09:38:54Z lecoanet $
+#
+#
+# Copyright (c) 1999 CENA --
+#
+# See the file "Copyright" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+#
+#
+
+__version__ = "$Revision: 1908 $"
+__revision__ = "$Revision: 1908 $"
+
+from Tkinter import *
+import new
+import os
+import locale, types
+import traceback
+
+ZINC_CURRENT_POSITION = -2
+ZINC_SPEED_VECTOR = -3
+ZINC_LEADER = -4
+ZINC_CONNECTION = -5
+_LIBLOADED = 0
+_VERSION = ""
+ZINC_NO_PART = ""
+
+# current part dictionnary
+ZINC_DPART = { 'position' : ZINC_CURRENT_POSITION,
+ 'speedvector' : ZINC_SPEED_VECTOR ,
+ 'leader' : ZINC_LEADER,
+ 'connection' : ZINC_CONNECTION}
+# notes : 'field' will be return when currentpart is a field
+
+def havetkzinc( window ):
+ '''load Zinc dynamic sharable object library , test if everything is ok
+if ok :return zinc version
+if nok : return 0 '''
+ global _LIBLOADED
+ global _VERSION
+ if ( _LIBLOADED == 1 ) :
+ return _VERSION
+ try:
+ if os.environ.has_key( 'auto_path' ):
+ ldir = os.environ['auto_path'].split( ':' )
+ ldir.reverse()
+ for adir in ldir :
+ window.tk.call( 'eval',
+ "set auto_path "
+ + "[linsert $auto_path 0 %s]" % ( adir ) )
+ window.tk.call( 'eval', 'package require Tkzinc' )
+ # Call a function from the package to autoload it
+ # and verify that all is OK.
+ sversion = window.tk.call( 'zinc' ) + " Zinc.py %s" % __version__
+ except TclError:
+ traceback.print_exc()
+ return 0
+ _LIBLOADED = 1
+ _VERSION = sversion
+ return sversion
+
+class ZincException:
+ def __call__( self ):
+ raise self
+
+ def __init__( self, message ):
+ self.message = message
+
+ def __str__( self ):
+ return self.message
+
+class Zinc( Widget ):
+ def __str__( self ):
+ return( "Zinc instance" )
+ def __init__( self, master = None, cnf = None, **kw ):
+ if kw.has_key( 'backward_compatibility' ):
+ self.currentpart = self.__oldcurrentpart
+ self.configure = self.__oldconfigure
+ self.scale = self.__oldscale
+ self.translate = self.__oldtranslate
+ del kw['backward_compatibility']
+ #Pour éviter des effets de bord
+ #si on met comme valeur par défaut de cnf
+ #à {}
+ if cnf is None :
+ cnf = {}
+ if master :
+ self.version = havetkzinc( master )
+ else:
+ master = Frame()
+ master.pack()
+ self.version = havetkzinc( master )
+ Widget.__init__( self, master, 'zinc', cnf, kw )
+ self.items = {}
+ #BootStrap Root
+ classe = eval( 'Group' )
+ obj = None
+ kw['id'] = 1
+ obj = new.instance( classe, kw )
+ self.items[1] = obj
+
+ def mainloop( self ):
+ """
+ Run the events mainloop
+ """
+ self.tk.mainloop()
+
+ def add( self, itemType, *args, **kw ):
+ """
+ listTypes = zinc.add()
+ id = zinc.add(type, group)
+ id = zinc.add(type, group, initargs, **options)
+ type=[arc|curve|rectangle|triangles|tabular|track|waypoint|group|icon|map|reticle|text|window]
+ """
+ args = list( args )
+ args = args+list( self._options( kw ) )
+ try:
+ return self.tk.getint(
+ self.tk.call( self._w, 'add', itemType, *args ) )
+ except TclError, excpt :
+ ZincException( "%s\nType %s\nArgs : %s"%( excpt, itemType, args ) )()
+
+ def addtag( self, *args ):
+ """
+ zinc.addtag(tag, searchSpec)
+ This command add the given tag to all items matching
+ the search specification.
+ If the tag is already present on some item,
+ nothing is done for that item.
+ The command has no effect if no item satisfy
+ the given criteria. The command returns an empty string.
+ """
+ self.tk.call( self._w, 'addtag', *args )
+
+ def addtag_above( self, newtag, tagOrId ):
+ """
+ zinc.addtag_above(tag, tagOrId)
+ """
+ self.addtag( newtag, 'above', tagOrId )
+
+ def addtag_all( self, newtag ):
+ """
+ A ne plus utiliser
+ Utiliser addtag_withtag
+ """
+ self.addtag( newtag, 'all' )
+
+ def addtag_ancestors( self, newtag, tagOrId, *ltagOrId ):
+ """
+ zinc.addtag_ancestors(tag, tagOrId, *listTagOrId)
+ """
+ self.addtag( newtag, 'ancestors', tagOrId, *ltagOrId )
+
+ def addtag_atpriority( self, newtag, pri, tagOrId = 1 ):
+ """
+ zinc.addtag_atpriority(tag, priority, tagOrId = 1)
+ """
+
+ self.addtag( newtag, 'atpriority', pri, tagOrId )
+
+ def addtag_below( self, newtag, tagOrId ):
+ """
+ zinc.addtag_below(tag, tagOrId)
+ """
+ self.addtag( newtag, 'below', tagOrId )
+
+ def addtag_closest( self, newtag, x, y, halo = None, startItem = 1, recursive = 0 ):
+ """
+ zinc.addtag_closest(tag, x, y, halo = None, startItem = 1, recursive = 0)
+ """
+ self.addtag( newtag, 'closest', x, y, halo, startItem, recursive )
+
+ def addtag_enclosed( self, newtag, x1, y1, x2, y2, inGroup = 1, recursive = 0 ):
+ """
+ zinc.addtag_enclosed(tag, x1, y1, x2, y2, inGroup = 1, recursive = 0)
+ """
+ self.addtag( newtag, 'enclosed', x1, y1, x2, y2, inGroup, recursive )
+
+ def addtag_overlapping( self, newtag, x1, y1, x2, y2, inGroup = 1, recursive = 0 ):
+ """
+ zinc.addtag_overlapping(tag, x1, y1, x2, y2, inGroup = 1, recursive = 0)
+ """
+ self.addtag( newtag, 'overlapping', x1, y1, x2, y2, inGroup, recursive )
+
+ def addtag_withtag( self, newtag, tagOrId ):
+ """
+ zinc.addtag_withtag(tag, tagOrId)
+ """
+ self.addtag( newtag, 'withtag', tagOrId )
+
+ def addtag_withtype( self, newtag, type, tagOrId = 1 ):
+ """
+ zinc.addtag_withtype(tag, type, tagOrId = 1)
+ """
+ self.addtag( newtag, 'withtype', type, tagOrId )
+
+ def anchorxy( self, *args ):
+ """
+ (x, y) = zinc.anchorxy(tagOrId, anchor)
+ """
+ return self.tk.call( self._w, 'anchorxy', *args )
+
+ def bbox( self, *args ):
+ """
+ (xo, yo, xc, yc) = zinc.bbox(tagOrId, ?fieldIndex?)
+ """
+ return self.tk.call( self._w, 'bbox', *args )
+
+ def becomes( self ):
+ """
+ zinc.becomes()
+ """
+ self.tk.call( self._w, 'becomes' )
+
+ def bind_tag( self, tagOrId, sequence = None, func = None, add = None ):
+ '''
+ return a funcid which can be usefull for unbinding
+ listBindings = zinc.bind_tag(tagOrId)
+ listbindings = zinc.bind_tag(tagOrId, sequence)
+ zinc.bind_tag(tagOrId, sequence, '')
+ zinc.bind_tag(tagOrId, sequence, command)
+ '''
+ return self._bind( ( self._w, 'bind', tagOrId ),
+ sequence, func, add )
+
+ def cget( self, option ):
+ """
+ val = zinc.cget(option)
+ """
+ return self.tk.call( self._w, 'cget', '-' + option )
+
+ def chggroup( self, *args ):
+ """
+ zinc.chggroup(tagOrId, group, ?adjustTransform?)
+ """
+ self.tk.call( self._w, 'chggroup', *args )
+
+ def clone( self, *args, **kw):
+ """
+ id = zinc.clone(tagOrId, **attributs)
+ """
+ args = list( args ) + list( self._options( kw ) )
+ return self.tk.call( self._w, 'clone', *args)
+
+ def __oldconfigure( self, **kw ):
+ return Widget.configure( self, **kw )
+
+ def configure( self, **kw ):
+ """
+ listOptions = zinc.configurez()
+ listOptions = zinc.configurez(option)
+ zinc.configurez(**options)
+ """
+ res = Widget.configure( self, **kw )
+ dico = {}
+ if res:
+ for i, j in res.items():
+ dico[i] = j[3:]
+ return dico
+
+ def contour( self, *args ):
+ """
+ contourNum = zinc.contour(tagOrId)
+ contourNum = zinc.contour(tagOrId, operatorAndFlag, coordListOrTagOrId)
+ """
+ return self.tk.call( self._w, 'contour', *args )
+
+ def coords( self, *args ):
+ """
+ zinc.coords(tagOrId, contourIndex)
+ zinc.coords(tagOrId, contourIndex, coordList)
+ zinc.coords(tagOrId, contourIndex, coordIndex)
+ zinc.coords(tagOrId, contourIndex, coordIndex, coordList)
+ zinc.coords(tagOrId, 'remove', contourIndex, coordIndex)
+ zinc.coords(tagOrId, 'add', contourIndex, coordList)
+ zinc.coords(tagOrId, 'add', contourIndex, coordIndex, coordList)
+ zinc.coords(tagOrId)
+ zinc.coords(tagOrId, coordList)
+ zinc.coords(tagOrId, 'remove', coordIndex)
+ zinc.coords(tagOrId, 'add', coordList)
+ """
+ return self.tk.call( self._w, 'coords', *args )
+
+ def __buggyoldcurrentpart( self ):
+ '''
+ return a string (result from zinc current part function) and an
+ integer representing either the number of the field either
+ the number of the item part either ZINC_NO_PART
+ '''
+ scurrentp = self.tk.call( self._w, 'currentpart' )
+ if scurrentp == "":
+ rvalue = ZINC_NO_PART
+ else:
+ try:
+ rvalue = locale.atoi( scurrentp )
+ except:
+ try:
+ rvalue = ZINC_DPART[scurrentp]
+ except:
+ rvalue = ZINC_NO_PART
+ else:
+ # string to integer succeeded
+ scurrentp = "field"
+ return( scurrentp, rvalue )
+
+ def __oldcurrentpart( self ):
+ '''return a string and an integer ;
+the string is among "field", "position", "speedvector", "leader", "connection", "",
+the number is the number of the part , or the field number in case of "field";
+ex:
+no part return '', ZINC_NO_PART
+'''
+ scurrentp = self.tk.call( self._w, 'currentpart' )
+ print "Zinc::__oldcurrentpart scurrentp = [%s]" % scurrentp
+ # warning : read this first :
+ # return a string among 'position', 'speedvector', 'leader', 'connection' ,''
+ # or an int representing the number of a field label
+ #
+ # print "Zinc::currentpart cp=%s ,type(cp)=%s" % (scurrentp,type(scurrentp))
+ if scurrentp == "":
+ rvalue = ZINC_NO_PART
+ elif type( scurrentp ) == type( 1 ):
+ # meaning a field
+ # the subtil thing is here ! warning !
+ rvalue = scurrentp
+ scurrentp = "field"
+ else:
+ # scurrentp is a string different from ""
+ try:
+ rvalue = ZINC_DPART[scurrentp]
+ except:
+ print "Zinc::currentpart unknown item part"
+ rvalue = ZINC_NO_PART
+
+ return scurrentp, rvalue
+
+ def currentpart( self ):
+ '''
+ num = zinc.currentpart()
+ '''
+ return str( self.tk.call( self._w, 'currentpart' ) )
+
+
+ def cursor( self, *args ):
+ """
+ zinc.cursor(tagOrId, index)
+ """
+ self.tk.call( self._w, 'cursor', *args )
+
+ def dchars( self, *args ):
+ """
+ zinc.dchars( tagOrId, first )
+ zinc.dchars( tagOrId, first,last )
+ """
+ self.tk.call( self._w, 'dchars', *args )
+
+ def dtag( self, *args ):
+ """
+ zinc.dtag(tagOrId)
+ zinc.dtag(tagOrId, tagToDelete)
+ """
+ self.tk.call( self._w, 'dtag', *args )
+
+ def find( self, *args ):
+ return self._getints(
+ self.tk.call( self._w, 'find', *args ) ) or ()
+
+ def find_above( self, tagOrId ):
+ """
+ listItems=zinc.find_above(tagOrId)}
+ """
+ return self.find( 'above', tagOrId )
+
+ def find_all( self ):
+ return self.find( 'all' )
+
+ def find_ancestors( self, newtag, tagOrId, *tagOrId2 ):
+ """
+ listItems=zinc.find_ancestor(tag, tagOrId, ?tagOrId2?)
+ """
+ return self.find( newtag, 'ancestors', tagOrId, *tagOrId2 )
+
+ def find_atpriority( self, pri, *tagOrId ):
+ """
+ listItems=zinc.find_atpriority(pri, ?tagOrId?)
+ """
+ return self.find( 'atpriority', pri, *tagOrId )
+
+ def find_below( self, tagOrId ):
+ """
+ listItems=zinc.find_below(tagOrId)
+ """
+ return self.find( 'below', tagOrId )
+
+ def find_closest( self, x, y, *options ):
+ """
+ listItems=zinc.find_closest(x, y, ?halo?, ?startItem?, ?recursive?)
+ """
+ return self.find( 'closest', x, y, *options )
+
+ def find_enclosed( self, x1, y1, x2, y2 ):
+ """
+ listItems=zinc.find_enclosed(x1, y1, x2, y2, inGroup=1, recursive=0)
+ """
+ return self.find( 'enclosed', x1, y1, x2, y2 )
+
+ def find_overlapping( self, x1, y1, x2, y2, *options ):
+ """
+ listItems=zinc.find_overlapping( x1, y1, x2, y2, ?inGroup?, ?recursive?)
+ """
+ return self.find( 'overlapping', x1, y1, x2, y2, *options )
+
+ def find_withtag( self, tagOrId ):
+ """
+ listItems=zinc.find_withtag( tagOrId)
+ """
+ return self.find( 'withtag', tagOrId )
+
+ def find_withtype( self, type, *tagOrId ):
+ """
+ listItems=zinc.find_withtype( type, ?tagOrId?)
+ """
+ return self.find( 'withtype', type, *tagOrId )
+
+
+ def fit( self, *args ):
+ """
+ listControls=zinc.fit(coordList,error)
+ """
+ return self.tk.call( self._w, 'fit', *args )
+
+ def focus( self, *args ):
+ """
+ zinc.focus(tagOrId, ?itemPart?)
+ """
+ self.tk.call( self._w, 'focus', *args )
+
+ def gdelete( self, *args ):
+ """
+ zinc.gdelete(gradientName)
+ """
+ self.tk.call( self._w, 'gdelete', *args )
+
+ def gettags( self, *args ):
+ """
+ listTags=zinc.gettags(tagorid)
+ """
+ return self.tk.splitlist( self.tk.call( self._w, 'gettags', *args ) )
+
+ def gname( self, *args ):
+ """
+ zinc.gname(gradientDesc, gradientName)
+ bExist=zinc.gname(gradientName)
+ """
+ return self.tk.call( self._w, 'gname', *args )
+
+ def group( self, *args ):
+ """
+ group=zinc.group(tagOrId)
+ """
+ return self.tk.call( self._w, 'group', *args )
+
+ def hasanchors( self, *args ):
+ """
+ bool=zinc.hasanchors(tagOrId)
+ """
+ return self.tk.call( self._w, 'hasanchors', *args )
+
+ def hasfields( self, *args ):
+ """
+ bool=zinc.hasfields(tagOrId)
+ """
+ return self.tk.call( self._w, 'hasfield', *args )
+
+ def hastag( self, *args ):
+ """
+ bool=zinc.hastag(tagOrId, tag)
+ """
+ return self.tk.call( self._w, 'hastag', *args )
+
+ def index( self, *args ):
+ """
+ num = zinc.index(tagOrId, index)
+ """
+ return self.tk.call( self._w, 'tagOrId', *args )
+
+ def insert( self, *args ):
+ """
+ zinc.insert(tagOrId, before, string)
+ """
+ self.tk.call( self._w, 'insert', *args )
+
+ def itemcget( self, tagOrId, option ):
+ """
+ val=zinc.itemcget(tagOrId, attr)
+ """
+ return self.tk.call( self._w, 'itemcget', tagOrId, '-'+option )
+
+ def itemfieldget( self, tagOrId, field, option ):
+ """
+ val=zinc.itemcget(tagOrId, field, attr)
+ """
+ return self.tk.call( self._w, 'itemcget', tagOrId, field, '-'+option )
+
+ def itemconfigure( self, tagOrId, field=None, **kw ):
+ '''
+ either get the dictionnary of possible attributes (if kw is None)
+ either allow to set Items attributes or Field attributes
+
+ listAttribs=zinc.itemconfigure(tagOrId)
+ listAttribs=zinc.itemconfigure(tagOrId, attrib)
+ zinc.itemconfigure(tagOrId, **attributs)
+ listAttribs=zinc.itemconfigure(tagOrId, fieldIs, attrib)
+ zinc.itemconfigure(TagOrId,fieldId,**attributs)
+ '''
+ if not kw:
+ cnf = {}
+ for var_x in self.tk.split(
+ field != None and self.tk.call( self._w, 'itemconfigure',
+ ( tagOrId, field ) ) or
+ self.tk.call( self._w, 'itemconfigure', ( tagOrId, ) ) ):
+ cnf[var_x[0][1:]] = ( var_x[0][1:], ) + var_x[1:]
+ return cnf
+ if field != None:
+ args = ( tagOrId, str( field ), )+ self._options( {}, kw )
+ self.tk.call( self._w, 'itemconfigure', *args )
+ else:
+ args = ( tagOrId, ) + self._options( {}, kw )
+ self.tk.call( self._w, 'itemconfigure', *args )
+
+ # _dp voir si cette instruction est a execute ici
+ # permet de creer un synonyme de itemconfigure
+ itemconfig = itemconfigure
+
+ def loweritem( self, *args ):
+ """
+ zinc.loweritem(tagOrId)
+ zinc.loweritem(tagOrId, belowThis)
+ Reorder all the items given by tagOrId so that
+ they will be under the item given by belowThis.
+ If tagOrId name more than one item,
+ their relative order will be preserved.
+ If tagOrId doesn't name an item, an error is raised.
+ If belowThis name more than one item, the bottom most them is used.
+ If belowThis doesn't name an item, an error is raised.
+ If belowThis is omitted the items are put
+ at the bottom most position of their respective groups.
+ The command ignore all items named by tagOrId
+ that are not in the same group than belowThis or,
+ if not specified, in the same group than the first item
+ named by tagOrId. The command returns an empty string.
+ As a side affect of this command, the -priority attribute
+ of all the reordered items is ajusted to match the priority
+ of the belowThis item (or the priority of the bottom most item)
+ """
+ self.tk.call( self._w, 'lower', *args )
+
+ def monitor( self, *args ):
+ """
+ bool = zinc.monitor()
+ zinc.monitor(bool)
+ """
+ return self.tk.call( self._w, 'monitor', *args )
+
+ def numparts( self, *args ):
+ """
+ num = zinc.numparts(tagOrId)
+ """
+ return self.tk.call( self._w, 'numparts', *args )
+
+ def postcript( self, *args ):
+ """
+ Not Yet Implemented
+ zinc.postscript()
+ """
+ return self.tk.call( self._w, 'postscript', *args )
+
+ def raiseitem( self, *args ):
+ """
+ Correspond à l'appel raise de la documentation
+ le mot raise est reservé en python
+ zinc.raiseitem(tagOrId)
+ zinc.raiseitem(tagOrId, aboveThis)
+ """
+ self.tk.call( self._w, 'raise', *args )
+
+ def remove( self, *args ):
+ """
+ zinc.remove(tagOrId, ?tagOrId,...?)
+ """
+ self.tk.call( self._w, 'remove', *args )
+
+ def rotate( self, *args ):
+ """
+ zinc.rotate(tagOrId, angle)
+ zinc.rotate(tagOrId, angle, centerX, centerY)
+ """
+ self.tk.call( self._w, 'rotate', *args )
+
+ def __oldscale( self, xFactor=None, yFactor=None, tagOrId=None ):
+ if yFactor == None:
+ return self.tk.getdouble( self.tk.call( 'scale' ) )
+ else:
+ if tagOrId == None:
+ self.tk.call( self._w, 'scale', xFactor, yFactor )
+ else:
+ self.tk.call( self._w, 'scale', tagOrId, xFactor, yFactor )
+
+ def scale( self, *args ):
+ """
+ zinc.scale(tagOrIdOrTName, xFactor, yFactor)
+ zinc.scale(tagOrIdOrTName, xFactor, yFactor, centerX, centerY)
+ Add a scale factor to the items or the transform described
+ by tagOrId.
+ If tagOrId describes a named transform then this transform
+ is used to do the operation. If tagOrId describes more than
+ one item then all the items are affected by the operation.
+ If tagOrId describes neither a named transform nor an item,
+ an error is raised.
+ A separate factor is specified for X and Y.
+ The optional parameters describe the center of scaling,
+ which defaults to the origin.
+ """
+ if not len( args ):
+ return self.tk.getdouble( self.tk.call( self._w, 'scale' ) )
+ else:
+ self.tk.call( self._w, 'scale', *args )
+
+ def select( self, *args ):
+ """
+ zinc.select('adjust', tagOrId, index)
+ Adjust the end of the selection in tagOrId
+ that is nearest to the character given by index so
+ that it is at index.
+ The other end of the selection is made the anchor
+ for future select to commands.
+ If the selection is not currently in tagOrId,
+ this command behaves as the select to command.
+ The command returns an empty string.
+ zinc.select('clear')
+ Clear the selection if it is in the widget.
+ If the selection is not in the widget,
+ the command has no effect. Return an empty string.
+ zinc.select('from', tagOrId, index)
+ Set the selection anchor point for the widget
+ to be just before the character given by index
+ in the item described by tagOrId.
+ The command has no effect on the selection,
+ it sets one end of the selection so that future
+ select to can actually set the selection.
+ The command returns an empty string.
+ (item,part) = zinc.select('item')
+ Returns a list of two elements.
+ The first is the id of the selected item
+ if the selection is in an item on this widget;
+ Otherwise the first element is an empty string.
+ The second element is the part of the item
+ (track, waypoint or tabular item only) or the empty string.
+ zinc.select('to', tagOrId, index)
+ Set the selection to be the characters that lies
+ between the selection anchor and index in the item described
+ by tagOrId. The selection includes the character given
+ by index and includes the character given by the anchor point
+ if index is greater or equal to the anchor point.
+ The anchor point is set by the most recent select adjust
+ or select from command issued for this widget.
+ If the selection anchor point for the widget is not currently
+ in tagOrId, it is set to the character given by index.
+ The command returns an empty string.
+ Manipulates the selection as requested by option.
+ tagOrId describes the target item.
+ This item must support text indexing and selection. I
+ f more than one item is referred to by tagOrId,
+ the first in display list order that support both text
+ indexing and selection will be used.
+ Some forms of the command include an index parameter,
+ this parameter describes a textual position within the
+ item and should be a valid index as described in
+ Text indices.
+ """
+ return self.tk.call( self._w, 'select', *args )
+
+ def skew( self, *args ):
+ """
+ zinc.skew(tagOrIdOrTName,xSkewAngle, ySkewAngle)
+ Add a skew (or shear) transform to the to the items
+ or the transform described by tagOrIdOrTName.
+ If tagOrId describes a named transform then this transform
+ is used to do the operation.
+ If tagOrId describes more than one item then all the
+ items are affected by the operation.
+ If tagOrId describes neither a named transform nor an item,
+ an error is raised. The angles are given in radian.
+ """
+ return self.tk.call( self._w, 'skew', *args )
+
+ def smooth( self, *args ):
+ """
+ zinc.smooth(coordList)
+ This command computes a sequence of segments
+ that will smooth the polygon described by the vertices
+ in coordList and returns a list of lists describing points
+ of the generated segments. These segments are approximating
+ a Bezier curve. coordList should be either a flat list
+ of an even number of coordinates in x, y order, or a list
+ of lists of point coordinates X, Y.
+ The returned list can be used to create or change the contour
+ of a curve item.
+ """
+ return self.tk.call( self._w, 'smooth', *args )
+
+ def tapply( self, *args ):
+ """
+ Not Yet Implemented
+ zinc.tapply()
+ """
+ return self.tk.call( self._w, 'tapply', *args )
+
+ def tcompose( self, *args ):
+ """
+ zinc.tcompose(tagOrIdOrTName, tName)
+ zinc.tcompose(tagOrIdOrTName, tName, invert)
+ """
+ return self.tk.call( self._w, 'tapply', *args )
+
+ def tdelete( self, *args ):
+ """
+ zinc.tdelete(tName)
+ Destroy a named transform.
+ If the given name is not found among the named transforms,
+ an error is raised.
+ """
+ self.tk.call( self._w, 'tdelete', *args )
+
+ def transform( self, *args ):
+ """
+ listCoords=zinc.transform(tagOrIdTo, coordList)
+ listCoords=zinc.transform(tagOrIdFrom, tagOrIdTo, coordList)
+ This command returns a list of coordinates obtained by transforming the coordinates given in coordList
+ from the coordinate space of the transform or item described by tagOrIdFrom to the coordinate space
+ of the transform or item described by tagOrIdTo.
+ If tagOrIdFrom is omitted it defaults to the window coordinate space.
+ If either tagOrIdFrom or tagOrIdTo describes more than one item,
+ the topmost in display list order is used. If either tagOrIdFrom or tagOrIdTo
+ doesn't describe either a transform or an item, an error is raised.
+ The coordList should either be a flat list containing an even number of coordinates
+ each point having two coordinates, or a list of lists each sublist of the form [ X Y ?pointtype? ].
+ The returned coordinates list will be isomorphic to the list given as argument.
+
+ It is possible to convert from window coordinate space to the coordinate space of any item.
+ This is done by omitting ?tagOrIdFrom? and specifying in tagOrIdTo, the id of the item.
+ It can also be done by using the predefined tag 'device' as first argument.
+
+ It is also possible to convert from the coordinate space of an item to the window coordinate
+ space by using the predefined tag 'device' as second argument.
+
+ """
+ return self._getdoubles( self.tk.call( self._w, 'transform', *args ) )
+
+#ANCIENNE IMPLEMENTATION
+ def __oldtranslate( self, dx=None, dy=None, tagOrId=None ):
+ if dx == None:
+ return self._getints( self.tk.call( 'translate' ) )
+ else:
+ if tagOrId == None:
+ self.tk.call( self._w, 'translate', dx, dy )
+ else:
+ self.tk.call( self._w, 'translate', tagOrId, dx, dy )
+
+ def translate( self, *args ):
+ """
+ zinc.translate(tagOrIdOrTName, xAmount, yAmount)
+ zinc.translate(tagOrIdOrTName, xAmount, yAmount, absolute)
+ Add a translation to the items or the transform described by tagOrIdOrTName.
+ If tagOrIdOrTName describes a named transform then this transform is used
+ to do the operation.
+ If tagOrIdOrTName describes more than one item then all the items are affected
+ by the opration.
+ If tagOrIdOrTName describes neither a named transform nor an item,
+ an error is raised. A separate value is specified for X and Y.
+ If the optionnal ?absolute? parameter is true,
+ it will set an absolute translation to the tagOrIdOrTName
+ """
+ if ( len( args ) == 1 ):
+ return self._getints( self.tk.call( self._w, 'translate' ) )
+ else:
+ self.tk.call( self._w, 'translate', *args )
+
+ def treset( self, *args ):
+ """
+ zinc.treset(tagOrIdOrTName)
+ Set the named transform or the transform for the items described by tagOrIdOrTName
+ to identity. If tagOrIdOrTName describes neither a named transform nor an item,
+ an error is raised.
+ """
+ self.tk.call( self._w, 'treset', *args )
+
+ def trestore( self, *args ):
+ """
+ zinc.trestore(tagOrId, tName)
+ Set the transform for the items described by tagOrId to the transform named by tName.
+ If tagOrId doesn't describe any item or if the transform named tName doesn't exist,
+ an error is raised.
+ """
+ self.tk.call( self._w, 'trestore', *args )
+
+ def tsave( self, *args ):
+ """
+ zinc.tsave(tName)
+ zinc.tsave(tagOrIdOrTName, tName)
+ zinc.tsave(tagOrIdOrTName, tName, invert)
+ Create (or reset) a transform associated with the name tName
+ with initial value the transform associated with the item tagOrIdOrTName.
+ If tagOrIdOrTName describes more than one item, the topmost in display list order is used.
+ If tagOrIdOrTName doesn't describe any item or named transformation, an error is raised.
+ If tName already exists, the transform is set to the new value.
+ This command is the only way to create a named transform.
+ If tagOrIdOrTName is not specified, the command returns a boolean telling
+ if the name is already in use.
+ The invert boolean, if specified, cause the transform to be inverted prior to be saved.
+
+ It is possible to create a new named transformation from the identity
+ by using the predefined tag 'identity': $zinc->tsave('identity', 'myTransfo');
+ """
+ return self.tk.call( self._w, 'tsave', *args )
+
+ def tget( self, *args ):
+ """
+ zinc.tget(tagOrId)
+ zinc.tget(tagOrIdOrTName, selector)
+ selector:={'all'|'translation'|'scale'|'rotation'|'skew'}
+ With only one argument, get the six elements of the 3x4 matrix
+ used in affine transformation for tagOrIdOrTName.
+ The result is compatible with the tset method.
+ With optional second parameter 'all' returns the transform
+ decomposed in translation, scale, rotation, skew
+ and return the list in this order,
+ With 'translation', 'scale', 'rotation', 'skew' optional
+ second parameter, returns the corresponding values.
+ """
+ return self.tk.call( self._w, 'tget', *args )
+
+ def tset( self, *args ):
+ """
+ zinc.tset(tagOrIdOrName, m00, m01, m10, m11, m20, m21)
+ Set the six elements of the 3x4 matrix used in affine transformation for tagOrIdOrTName.
+ BEWARE that depending on mij values,
+ it is possible to define a not inversible matrix which will end up in core dump.
+ This method must BE USED CAUTIOUSLY.
+ """
+ return self.tk.call( self._w, 'tset', *args )
+
+ def type( self, tagOrId ):
+ """
+ name=zinc.type(tagOrId)
+ If more than one item is named by tagOrId,
+ then the type of the topmost item in display list order is returned.
+ If no items are named by tagOrId, an error is raised.
+ """
+ return self.tk.call( self._w, 'type', tagOrId )
+
+ def vertexat( self, *args ):
+ """
+ (contour,vertex,edgevertex)=zinc.vertexat(tagOrId,x,y)
+ """
+ return self.tk.call( self._w, 'vertexat', *args )
+
+ def xview(self, *args):
+ """Query and change horizontal position of the view."""
+ if not args:
+ return self._getdoubles(self.tk.call(self._w, 'xview'))
+ self.tk.call((self._w, 'xview') + args)
+ def xview_moveto(self, fraction):
+ """Adjusts the view in the window so that FRACTION of the
+ total width of the canvas is off-screen to the left."""
+ self.tk.call(self._w, 'xview', 'moveto', fraction)
+ def xview_scroll(self, number, what):
+ """Shift the x-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
+ self.tk.call(self._w, 'xview', 'scroll', number, what)
+ def yview(self, *args):
+ """Query and change vertical position of the view."""
+ if not args:
+ return self._getdoubles(self.tk.call(self._w, 'yview'))
+ self.tk.call((self._w, 'yview') + args)
+ def yview_moveto(self, fraction):
+ """Adjusts the view in the window so that FRACTION of the
+ total height of the canvas is off-screen to the top."""
+ self.tk.call(self._w, 'yview', 'moveto', fraction)
+ def yview_scroll(self, number, what):
+ """Shift the y-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
+ self.tk.call(self._w, 'yview', 'scroll', number, what)
+
+class ZincItem:
+ def __init__( self, zinc, itemType, group = 1, *args, **kw ):
+ self.zinc = zinc
+ texture = None
+ fillpatern = None
+ scale = None
+ translate = None
+ if kw.has_key( 'texture' ):
+ texture = kw['texture']
+ del kw['texture']
+
+ if kw.has_key( 'fillpatern' ):
+ fillpastern = kw['fillpatern']
+ del kw['fillpatern']
+
+ if kw.has_key( 'scale' ):
+ scale = kw['scale']
+ del kw['scale']
+
+ if kw.has_key( 'rotate' ):
+ rotate = kw['rotate']
+ del kw['rotate']
+
+ if kw.has_key( 'translate' ):
+ translate = kw['translate']
+ del kw['translate']
+
+ if kw.has_key( 'cloneid' ):
+ cloneid = kw['cloneid']
+ del kw['cloneid']
+ else:
+ cloneid = 0
+ group = str( group )
+ # sys.stdout.flush()
+ if cloneid == 0 :
+ self.id = zinc.add( itemType, group, *args, **kw )
+ else :
+ self.id = self.zinc.clone(cloneid, *args, **kw)
+
+ zinc.items[self.id] = self
+ texture = None
+ if fillpatern:
+ self.itemconfigure( fillpatern )
+ if scale:
+ self.scale( scale )
+ if translate:
+ self.translate( translate )
+
+
+ def __str__( self ):
+ return str( self.id )
+
+ def __repr__( self ):
+ return str( self.id )
+
+ def bbox( self, *args ):
+ return self.zinc.bbox( self.id, *args )
+
+ def clone( self, *args, **kw):
+ '''id = zincitem.clone(*args,**kw) '''
+ # print "ZincItem::clone"
+ # on cherche tagOrId
+ # nidcloned = self.find_above(tagOrId)
+ sclonedtype = self.type()
+ sclonedgroupid = self.zinc.group(self.id)
+
+ # ajout cle 'cloneid' (voir ZincItem::__init__)
+ kw['cloneid'] = self.id
+ # on cree un nouveau ZincItem meme type,
+ return(ZincItem(self.zinc, sclonedtype, sclonedgroupid, **kw ))
+
+ def delete( self ):
+ del self.zinc.items[self.id]
+ try:
+ self.zinc.remove( self.id )
+ except:
+ pass
+ def __getitem__( self, key ):
+ '''allow to get attribute by self["key"] '''
+ if ( key == "coords" ):
+ return self.zinc.coords( self.id )
+ return self.zinc.itemcget( self.id, key )
+
+ def __setitem__( self, key, value ):
+ '''allow to set item attrbutes, eg. for a track position attributes
+ just writing :
+ a = ZincItem(myzinc, ...)
+ a["position"] = (x,y)
+ Notes : when setting multiple attributes
+ using itemconfigure is more efficient '''
+ if ( key is "coords" ):
+ self.zinc.coords( self.id, value )
+ else:
+ self.zinc.itemconfigure( self.id, **{key:value} )
+
+ def getGroup( self ):
+ groupid = self.zinc.group( self.id )
+ return self.zinc.items[groupid]
+
+ def keys( self ):
+ if not hasattr( self, '_keys' ):
+ self._keys = {}
+ config = self.zinc.itemconfig( self.id )
+ for x in config.keys():
+ self._keys[x] = config[x][1]
+ return self._keys
+
+ def has_key( self, key ):
+ return key in self.keys()
+
+ def bind( self, sequence=None, command=None, add=None ):
+ '''return a funcid which can be used to unbind
+notes: unbinding can be done by bind("<seq>","") or using native tkinter
+unbind method '''
+ return( self.zinc.bind_tag( self.id, sequence, command, add ) )
+
+ def cget( self, attr ):
+ return self.zinc.itemcget( self.id, attr )
+
+ def coords( self, *args, **kw ):
+ return self.zinc.coords( self.id, *args, **kw )
+
+ def fieldcget( self, field, attr ):
+ return self.zinc.itemfieldcget( self.id, field, attr )
+
+ def itemconfigure( self, field=None, **kw ):
+ self.zinc.itemconfigure( self.id, field, **kw )
+
+ def rotate( self, *args ):
+ return self.zinc.rotate( self.id, *args )
+
+ def scale( self, *args ):
+ return self.zinc.scale( self.id, *args )
+
+ def transforms( self, *args ):
+ """
+ zincitem.transform(tozincitem, coordList)
+ This command returns a list of coordinates obtained by transforming the coordinates given in coordList
+ from the coordinate space of item to the coordinate space
+ of the tozincitem item.
+ The coordList should either be a flat list containing an even number of coordinates
+ each point having two coordinates, or a list of lists each sublist of the form [ X Y ?pointtype? ].
+ The returned coordinates list will be isomorphic to the list given as argument.
+ """
+ return self.zinc.transforms( self.id, *args )
+
+ def translate( self, *args ):
+ """
+ zincitem.translate( xAmount, yAmount)
+ zincitem.translate( xAmount, yAmount, absolute)
+ Add a translation to the item.
+ A separate value is specified for X and Y.
+ If the optionnal ?absolute? parameter is true,
+ it will set an absolute translation to the item
+ """
+ self.zinc.translate( self.id, *args )
+
+ def tset( self, *args ):
+ """
+ zincitemtset(m00, m01, m10, m11, m20, m21)
+ Set the six elements of the 3x4 matrix used in affine transformation.
+ BEWARE that depending on mij values,
+ it is possible to define a not inversible matrix which will end up in core dump.
+ This method must BE USED CAUTIOUSLY.
+ """
+ self.zinc.tset( self.id, *args )
+
+ def type( self ):
+ """
+ name=zincitemtype()
+ This command returns the type of the item.
+ """
+ return self.zinc.type( self.id )
+
+ def tsave( self, *args ):
+ """
+ zincitemtsave( tName)
+ zincitemtsave( tName, invert)
+ Create a transform associated with the name tName
+ with initial value the transform associated with the item.
+ If tName already exists, the transform is set to the new value.
+ This command is the only way to create a named transform.
+ The invert boolean, if specified, cause the transform to be inverted prior to be saved.
+ """
+ return self.zinc.tsave( self.id, *args )
+
+ def treset( self, *args ):
+ """
+ zincitemtreset()
+ Set the named transform or the transform for the item
+ to identity. If there are no named transform,
+ an error is raised.
+ """
+ self.zinc.treset( self.id, *args )
+
+ def trestore( self, *args ):
+ """
+ zincitemtrestore( tName)
+ Set the transform for the item to the transform named by tName.
+ If the transform named tName doesn't exist, an error is raised.
+ """
+ self.zinc.trestore( self.id, *args )
+
+ def tget( self, *args ):
+ """
+ zincitemtget()
+ zincitemtget(selector)
+ selector:={'all'|'translation'|'scale'|'rotation'|'skew'}
+ With only one argument, get the six elements of the 3x4 matrix
+ used in affine transformation.
+ The result is compatible with the tset method.
+ With optional second parameter 'all' returns the transform
+ decomposed in translation, scale, rotation, skew
+ and return the list in this order,
+ With 'translation', 'scale', 'rotation', 'skew' optional
+ second parameter, returns the corresponding values.
+ """
+ return self.zinc.tget( self.id, *args )
+
+
+class Arc( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ The arc type expects a list of four floating point numbers xo yo xc yc,
+ giving the coordinates of the origin and the corner of the enclosing rectangle.
+ The origin should be the top left vertex of the enclosing rectangle and the corner
+ the bottom right vertex of the rectangle.
+ """
+ ZincItem.__init__( self, zinc, 'arc', *args, **kw )
+
+class Group( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ These type do not expect type specific arguments.
+ """
+ ZincItem.__init__( self, zinc, 'group', *args, **kw )
+
+ def getGroup( self ):
+ """Retourne l'objet de type Group
+ auquel est attache l'item"""
+ ###Gestion du boostrap
+ if self.id == 1:
+ return self.zinc.items[1]
+ else:
+ return ZincItem.getGroup( self )
+
+ #TODO: Extension. Renvoie les références aux ZincItems contenus dans le Groupe
+ def getNode( self ):
+ """
+ """
+ pass
+
+class Icon( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ These type do not expect type specific arguments.
+ """
+ ZincItem.__init__( self, zinc, 'icon', *args, **kw )
+
+class Map( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ These type do not expect type specific arguments.
+ """
+ ZincItem.__init__( self, zinc, 'map', *args, **kw )
+
+class Curve( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ The curve type expects either a flat list or a list of lists.
+ In the first case, the flat list must be a list of floating point numbers
+ x0 y0 x1 y1 ... xn yn, giving the coordinates of the curve vertices.
+ The number of values should be even (or the last value will be discarded)
+ but the list can be empty to build an empty invisible curve.
+ In the second case,thelist must contain lists of 2 or 3 elements:
+ xi, yi and and an optionnal point type. Currently,
+ the only available point type is 'c' for a cubic bezier control point.
+ For example, the following list is an example of 2 beziers segments
+ with a straight segment in-between:
+ ( [x0, y0], [x1, y1, 'c'], [x2, y2, 'c'], [x3, y3], [x4, y4, 'c'], [x5, y5] )
+
+ As there is only on control point, [x4, y4, 'c'] ,
+ for the second cubic bezier,
+ the omitted second control point will be defaulted to the same point.
+ a named tuple contours can give to define new contours in curve.
+ contours=(<contour1>,...)
+ <contour>=(<point1>,...)
+ A curve can be defined later with the contour or coords commands.
+ As a side effect of the curve behavior,
+ a one vertex curve is essentially the same as an empty curve,
+ it only waste some more memory.
+
+ """
+ contours = []
+ if kw.has_key( 'contours' ):
+ contours = kw['contours']
+ del kw['contours']
+ ZincItem.__init__( self, zinc, 'curve', *args, **kw )
+ for contour in contours:
+ self.zinc.contour( self.id, *contour )
+
+
+class Rectangle( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ The rectangle type expects a list of four floating point numbers xo yo xc yc,
+ giving the coordinates of the origin and the corner of the rectangle.
+ """
+ ZincItem.__init__( self, zinc, 'rectangle', *args, **kw )
+
+class Reticle( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ These type do not expect type specific arguments.
+ """
+ ZincItem.__init__( self, zinc, 'reticle', *args, **kw )
+
+class Tabular( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ ZincItem.__init__( self, zinc, 'tabular', *args, **kw )
+
+class Text( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ """
+ These type do not expect type specific arguments.
+ """
+ ZincItem.__init__( self, zinc, 'text', *args, **kw )
+
+class Track( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ ZincItem.__init__( self, zinc, 'track', *args, **kw )
+
+class WayPoint( ZincItem ):
+ def __init__( self, zinc, *args, **kw ):
+ ZincItem.__init__( self, zinc, 'waypoint', *args, **kw )
+
+
+# Class to hold mapinfos used by the Map Item class
+class Mapinfo:
+ def __init__( self, interp, name = None ):
+ """
+ @type name: string
+ @param name: Name of mapinfo. Must be used carrefully !
+ Create a new empty map description.
+ The new mapinfo object named name or internal id if name is omitted
+ """
+ if name :
+ self.name = name
+ else:
+ self.name = `id( self )`
+ self.interp = interp.tk
+ apply( self.interp.call, ( 'mapinfo', self.name, 'create' ) )
+
+ def __repr__( self ):
+ return self.name
+
+ def __del__( self ):
+ self.delete()
+
+ def delete( self ):
+ """
+ Delete the mapinfo object.
+ All maps that refer to the deleted mapinfo are updated to reflect the change.
+ """
+ self.interp.call( 'mapinfo', self.name, 'delete' )
+
+
+ def duplicate( self, *args ):
+ """
+ B{Optional}
+ @type name: Name of the new mapinfo
+ @param name: Must be use carrefully !!
+ Create a new mapinfo that is a exact copy of this mapinfo Object.
+ """
+ classe = Mapinfo
+ obj = new.instance( classe )
+ if len( args ):
+ new_name = args[0]
+ else:
+ new_name = str( obj )
+ self.interp.call( 'mapinfo', self.name, 'duplicate', new_name )
+ return obj
+
+ def add_text( self, text_style, line_style, x, y, text ):
+ """
+ Add a new graphical element to the mapinfo object text.
+ This element describes a line of text.
+ @type text_style: {normal|underlined}
+ @param text_style: text style
+ @type line_style: string
+ @param line_style: a line style (simple, dashed, dotted, mixed, marked) to be used for the underline
+ @type X: int
+ @param X: Coord on X axe
+ @type Y: int
+ @param Y: Coord on Y axe
+ @type text: string
+ @param : a string describing the text.
+
+ """
+ self.interp.call( 'mapinfo', self.name, 'add', 'text', text_style,
+ line_style, x, y, text )
+
+ def add_line( self, line_style, width, x1, y1, x2, y2 ):
+ """
+ Add a new graphical element to the mapinfo object line.
+ This element describes a line segment.
+ @type line_style: {simple|dashed|dotted|mixed|marked}
+ @param line_style: a line style
+ @type width: int
+ @param width: the line width in pixels
+ @type x1: int
+ @param x1: coords on X axe
+ @type x2: int
+ @param x2: coords on Y axe
+ @type x3: int
+ @param x3: end vertices on X axe
+ @type x4: int
+ @param x4: end vertices on Y axe
+ four integer values setting the X and Y coordinates of the two end vertices.
+ """
+ self.interp.call( 'mapinfo', self.name, 'add', 'line', line_style,
+ width, x1, y1, x2, y2 )
+
+ def add_arc( self, line_style, width, cx, cy, radius, start, extent ):
+ """
+ Add a new graphical element to the mapinfo object arc.
+
+ @type line_style: {simple|dashed|dotted|mixed|marked}
+ @param line_style: a line style
+ @type width: int
+ @param width: the line width in pixels
+ @type cx: int
+ @param cx: X of arc center
+ @type cy: int
+ @param cy: Y of arc center
+ @type radius: int
+ @param radius: the arc radius
+ @type start: int
+ @param start: the start angle (in degree)
+ @type extent: int
+ @param extent: the angular extent of the arc (in degree).
+
+ """
+ self.interp.call( 'mapinfo', self.name, 'add', 'arc', line_style,
+ width, cx, cy, radius, start, extent )
+
+ def add_symbol( self, x, y, index ):
+ """
+ Add a new graphical element to the mapinfo object symbol.
+ @type x: int
+ @param x: position on X
+ @type y: int
+ @param y: position on Y
+
+ @type index: int
+ @param : an integer setting the symbol index in the -symbols list of the map item
+
+ """
+ self.interp.call( 'mapinfo', self.name, 'add', 'symbol', x, y, index )
+
+ def count( self, type ):
+ """
+ @type type: {text|arc|line|symbol}
+ @param type:
+ Return an integer value that is the number of elements matching type in the mapinfo.
+ type may be one the legal element types
+ """
+ return self.interp.call( 'mapinfo', self.name, 'count', type )
+
+ def get( self, type, index ):
+ """
+ Return the parameters of the element at index with type type in the mapinfo.
+ The returned value is a list.
+ The exact number of parameters in the list and their meaning depend on type and is accurately described in mapinfo add.
+ type may be one the legal element types as described in the mapinfo add command.
+ Indices are zero based and elements are listed by type.
+ """
+ return self.interp.call( 'mapinfo', self.name, 'remove', type, index )
+
+ def replace( self, type, index, *args ):
+ """
+ Replace all parameters for the element at index with type type in the mapinfo.
+ The exact number and content for args depend on type and is accurately described in mapinfo add.
+ type may be one the legal element types as described in the mapinfo add command.
+ Indices are zero based and elements are listed by type.
+ """
+ return self.interp.call( 'mapinfo', self.name, 'replace',
+ type, index, args )
+
+ def remove( self, type, index ):
+ """
+ Remove the element at index with type type in the mapinfo.
+ type may be one the legal element types as described in the mapinfo add command. Indices are zero based and elements are listed by type.
+ """
+ return self.interp.call( 'mapinfo', self.name, 'remove', type, index )
+
+ def scale( self, factor ):
+ """
+ """
+ self.interp.call( 'mapinfo', self.name, 'scale', factor )
+
+ def translate( self, xAmount, yAmount ):
+ """
+ """
+ self.interp.call( 'mapinfo', self.name, 'translate', xAmount, yAmount )
+
+class Videomap ( Mapinfo ):
+ """
+ create a mapinfo from a proprietary
+ file format for simple maps, in use in french Air Traffic Control Centres. The format is the
+ binary cautra4 (with x and y in 1/8nm units)
+ """
+ def __init__( self, tk, *args ):
+ """
+ @type filename:
+ @param filename:
+ @type mapinfoname:
+ @param mapinfoname:
+ Load the videomap sub-map located at position index in the file named fileName into a mapinfo object named mapInfoName. It is possible, if needed, to use the videomap ids command to help translate a sub-map id into a sub-map file index.
+ """
+ self.tk = tk.tk
+ args = args + ( self, )
+ self.tk.call( 'videomap', 'load', *args )
+
+
+ def ids( self, filename ):
+ """
+ @type filename: string
+ @param filename: filename where to search syb-map
+ B{Class Method}
+ Return all sub-map ids that are described in the videomap file described by fileName.
+ The ids are listed in file order. This command makes possible to iterate through a videomap file
+ one sub-map at a time, to know how much sub-maps are there and to sort them according to their ids.
+ """
+ return self.tk.call( 'videomap', 'ids', filename )
+
+class Colors:
+ """
+ Classe abstraite utilitaire permettant de gérer sous forme d'objet
+ les couleurs aux formats Zinc
+ """
+ def __init__( self ):
+ self.lColors = []
+
+ #TODO:
+ def getColorsIter( self ):
+ """
+ Renvoie un itérateur sur les couleurs
+ """
+ return self.lColors.__iter__()
+
+ def addColor( self, color, alpha = 100,
+ colorposition = 0, mid_span_position = 50 ):
+ self.lColors.append( ( color, alpha, colorposition, mid_span_position ) )
+
+ def __repr__( self ):
+ res = ""
+ for i in self.lColors:
+ res = "%s%s;%s %s %s|" % ( res, i[0], i[1], i[2], i[3] )
+ return res[:-1]
+
+class AxialGradientColor( Colors ):
+ def __init__( self, *params ):
+ """
+ params : degre or x1, y1, x2, y2 which define angle and extension of the axe
+ =axial degre | gradient_step1 | ... | gradient_stepn or
+ =axial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
+ """
+ Colors.__init__( self )
+ count = 0
+ self.params = ""
+ for i in params:
+ self.params = "%s %s" % ( self.params, str( i ) )
+ count += 1
+ if ( count != 1 ) and ( count != 4 ):
+ raise Exception( "Bad Format of params %s" % count )
+
+ def __repr__( self ):
+ res = "=axial %s" % self.params
+ if not ( len( self.lColors ) ):
+ raise Exception( "Bad Format, must have one color less" )
+ res = "%s | %s" % ( res, Colors.__repr__( self ) )
+ return res
+
+class RadialGradientColor( Colors ):
+ def __init__( self, *params ):
+ """
+ =radial x y | gradient_step1 | ... | gradient_stepn or
+ =radial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
+ The x y parameters define the center of the radial.
+ The x1 y1 x2 y2 parameters define both the center and the extension of the radial.
+ """
+ Colors.__init__( self )
+ count = 0
+ self.params = ""
+ for i in params:
+ self.params = "%s %s" % ( self.params, str( i ) )
+ count += 1
+ if ( ( count!= 2 ) and ( count != 4 ) ):
+ raise Exception( "Bad Format of params %s"%count )
+
+ def __repr__( self ):
+ res = "=radial %s " % self.params
+ if not ( len( self.lColors ) ):
+ raise Exception( "Bad Format, must have one color less" )
+ res = "%s | %s" % ( res, Colors.__repr__( self ) )
+ return res
+
+class PathGradientColor( Colors ):
+ def __init__( self, *params ):
+ """
+ =path x y | gradient_step1 | ... | gradient_stepn
+ The x y parameters define the center of the gradient.
+ """
+ Colors.__init__( self )
+ count = 0
+ self.params = ""
+ for i in params:
+ self.params = "%s %s" % ( self.params, str( i ) )
+ count += 1
+ if ( count != 2 ):
+ raise Exception( "Bad Format of params %s" % count )
+
+ def __repr__( self ):
+ res = "=path %s " % self.params
+ if not ( len( self.lColors ) ):
+ raise Exception( "Bad Format, must have one color less" )
+ res = "%s | %s" % ( res, Colors.__repr__( self ) )
+ return res
+
+class ConicalGradientColor( Colors ):
+ def __init__( self, *params ):
+ """
+ =conical degre | gradient_step1 | ... | gradient_stepn or
+ =conical degre x y | gradient_step1 | ... | gradient_stepn or
+ =conical x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
+
+ The degre parameter defines the angle of the cone in the usual trigonometric sense.
+ The optional x y parameters define the center of the cone.
+ By default, it is the center of the bounding-box.
+ The x1 y1 x2 y2 parameters define the center and the angle of the cone.
+
+ All x and y coordinates are expressed in percentage of the bounding box,
+ relatively to the center of the bounding box.
+ So 0 0 means the center while -50 -50 means the lower left corner of the bounding box.
+
+ If none of the above gradient type specification is given,
+ the gradient will be drawn as an axial gradient with a null angle.
+ """
+ Colors.__init__( self )
+ count = 0
+ self.params = ""
+ for i in params:
+ self.params = "%s %s" % ( self.params, str( i ) )
+ count += 1
+ if ( count != 1 ) and ( count != 3 ) and ( count != 4 ):
+ raise Exception( "Bad Format of params %s" % count )
+
+ def __repr__( self ):
+ res = "=conical %s " % self.params
+ if not ( len( self.lColors ) ):
+ raise Exception( "Bad Format, must have one color less" )
+ res = "%s | %s" % ( res, Colors.__repr__( self ) )
+ return res
+
+
+# ---- self-test ----------------------------------------------------------
+if __name__ == '__main__':
+ from Tkinter import *
+ import Zinc
+ def createItem( zinc, group, ev ):
+ print >> sys.stdout, "CreateIHM"
+ sys.stdout.flush()
+ Zinc.Rectangle( zinc, group,
+ ( 100, 100, 150, 150 ),
+ linewidth = "10", linecolor = '#FFFF00',
+ relief = "roundgroove", filled = 1,
+ fillcolor = "red", tags = ( "hello", "test" ) )
+ sys.stdout.write( "hello_clic" + str( ev ) )
+
+ z = Zinc.Zinc( master = None, render = 1, height = 200, width = 400 )
+ g1 = Zinc.Group( z, 1 )
+ r = Zinc.Rectangle( z, g1, ( 0, 0, 400, 200 ),
+ linewidth = "10",
+ linecolor = '#FFFF00',
+ relief = "roundgroove",
+ filled = 1,
+ fillcolor = "#FFFFFF",
+ tags = ( "hello", "test" ) )
+ t = Zinc.Text( z, g1, position = ( 40, 100 ), text = z.version )
+# z.bind_tag("hello","<1>",lambda ev,z=z,g=g1 : createItem(z,g,ev))
+ z.configure( backcolor = 'black' )
+ z.pack()
+ z.mainloop()
+
+# Zinc.py ends here
+
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/__init__.py b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/__init__.py
new file mode 100755
index 0000000..d8e4f37
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/__init__.py
@@ -0,0 +1,4 @@
+from Zinc import *
+import graphics
+import geometry
+import pictorial
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/geometry.py b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/geometry.py
new file mode 100755
index 0000000..4063b61
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/geometry.py
@@ -0,0 +1,410 @@
+# -*- coding: iso-8859-1 -*-
+"""
+# Geometrical basic Functions :
+# -----------------------------
+# perpendicular_point
+# line_angle
+# linenormal
+# vertex_angle
+# arc_pts
+# rad_point
+# bezier_compute
+# bezier_segment
+# bezier_point
+"""
+
+from math import pi, radians, atan2, sin, cos
+
+# limite globale d'approximation courbe bezier
+bezierClosenessThreshold = .2
+def perpendicular_point (point, line):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::perpendicular_point
+ # retourne les coordonnées du point perpendiculaire abaissé d'un point
+ # sur une ligne
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # point : <coords> coordonnées du point de référence
+ # line : <coordsList> coordonnées des 2 points de la ligne de référence
+ #---------------------------------------------------------------------------
+ """
+ (p1, p2) = line
+
+ # cas partiuculier de lignes ortho.
+ min_dist = .01
+ if (abs(p2[1] - p1[1]) < min_dist) :
+ # la ligne de référence est horizontale
+ return (point[0], p1[1])
+
+ elif (abs(p2[0] - p1[0]) < min_dist) :
+ # la ligne de référence est verticale
+ return (p1[0], point[1])
+
+ a1 = float(p2[1] - p1[1]) / float(p2[0] - p1[0])
+ b1 = p1[1] - (a1 * p1[0])
+
+ a2 = -1.0 / a1
+ b2 = point[1] - (a2 * point[0])
+
+ x = (b2 - b1) / (a1 - a2)
+ y = (a1 * x) + b1
+
+ return (x, y)
+
+def line_angle(startpoint, endpoint):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::line_angle
+ # retourne l'angle d'un point par rapport à un centre de référence
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # startpoint : <coords> coordonnées du point de départ du segment
+ # endpoint : <coords> coordonnées du point d'extremité du segment
+ #---------------------------------------------------------------------------
+ """
+ angle = atan2(endpoint[1] - startpoint[1], endpoint[0] - startpoint[0])
+
+ angle += pi/2
+ angle *= float(180)/pi
+ if (angle < 0):
+ angle += 360
+
+ return angle
+
+def linenormal(startpoint, endpoint):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::linenormal
+ # retourne la valeur d'angle perpendiculaire à une ligne
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # startpoint : <coords> coordonnées du point de départ du segment
+ # endpoint : <coords> coordonnées du point d'extremité du segment
+ #---------------------------------------------------------------------------
+ """
+ angle = line_angle(startpoint, endpoint) + 90
+
+ if (angle > 360):
+ angle -= 360
+ return angle
+
+def vertex_angle(pt0, pt1, pt2):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::vertex_angle
+ # retourne la valeur de l'angle formée par 3 points
+ # ainsi que l'angle de la bisectrice
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # pt0 : <coords> coordonnées du premier point de définition de l'angle
+ # pt1 : <coords> coordonnées du deuxième point de définition de l'angle
+ # pt2 : <coords> coordonnées du troisième point de définition de l'angle
+ #---------------------------------------------------------------------------
+ """
+ angle1 = line_angle(pt0, pt1)
+ angle2 = line_angle(pt2, pt1)
+
+ if angle2 < angle1 :
+ angle2 += 360
+ alpha = angle2 - angle1
+ bisectrice = angle1 + (float(alpha)/2)
+
+ return (alpha, bisectrice)
+
+
+def arc_pts(center, radius, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::arc_pts
+ # calcul des points constitutif d'un arc
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # center : <coordonnées> centre de l'arc,
+ # radius : <dimension> rayon de l'arc,
+ # options :
+ # -angle : <angle> angle de départ en degré de l'arc (par défaut 0)
+ # -extent : <angle> delta angulaire en degré de l'arc (par défaut 360),
+ # -step : <dimension> pas de progresion en degré (par défaut 10)
+ #---------------------------------------------------------------------------
+ """
+ if center is None :
+ center = [0, 0]
+ if (options.has_key('angle')) :
+ angle = options['angle']
+ else:
+ angle = 0
+ if (options.has_key('extent')) :
+ extent = options['extent']
+ else:
+ extent = 360
+ if (options.has_key('step')) :
+ step = options['step']
+ else:
+ step = 10
+ pts = []
+
+ if (extent > 0 and step > 0) :
+ #A Verifier !
+ alpha = angle
+ while(alpha <= angle+extent):
+ (x_n, y_n) = rad_point(center, radius, alpha)
+ pts.append((x_n, y_n))
+ angle += step
+
+ elif (extent < 0 and step < 0) :
+ #Ca me semble buggue !!
+ #Si extent négatif, il faut aussi que step le soit
+ #Si ca boucle !
+ alpha = angle
+ while(alpha >= angle+extent):
+ pts.append(rad_point(center, radius, alpha))
+ alpha += step
+ else:
+ raise ValueError("Step and Extent havent the same sign")
+ return tuple(pts)
+
+def rad_point(center, radius, angle):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rad_point
+ # retourne le point circulaire défini par centre-rayon-angle
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # center : <coordonnée> coordonnée [x,y] du centre de l'arc,
+ # radius : <dimension> rayon de l'arc,
+ # angle : <angle> angle du point de circonférence avec le centre du cercle
+ #---------------------------------------------------------------------------
+ """
+ alpha = radians(angle)
+
+ xpt = center[0] + (radius * cos(alpha))
+ ypt = center[1] + (radius * sin(alpha))
+
+ return (xpt, ypt)
+
+def bezier_segment(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::bezier_segment
+ # Calcul d'une approximation de segment (Quadratique ou Cubique) de bezier
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # points : <[P1, C1, <C1>, P2]> liste des points définissant
+ # le segment de bezier
+ #
+ # options :
+ # -tunits : <integer> nombre pas de division des segments bezier
+ # (par défaut 20)
+ # -skipend : <boolean> : ne pas retourner le dernier point du
+ # segment (chainage)
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('tunits')) :
+ tunits = options['tunits']
+ else:
+ tunits = 20
+
+
+ if options.has_key('skipend'):
+ skipendpt = options['skipend']
+ else:
+ skipendpt = None
+
+ pts = []
+
+ if (skipendpt) :
+ lastpt = tunits-1
+ else:
+ lastpt = tunits
+ for i in xrange(0, lastpt+1):
+ if (i) :
+ t = (i/tunits)
+ else:
+ t = i
+ pts.append(bezier_point(t, coords))
+
+ return pts
+
+
+def bezier_point(t, coords):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::bezier_point
+ # calcul d'un point du segment (Quadratique ou Cubique) de bezier
+ # params :
+ # t = <n> (représentation du temps : de 0 à 1)
+ # coords = (P1, C1, <C1>, P2) liste des points définissant le segment
+ # de bezier P1 et P2 : extémités du segment et pts situés sur la courbe
+ # C1 <C2> : point(s) de contrôle du segment
+ #---------------------------------------------------------------------------
+ # courbe bezier niveau 2 sur (P1, P2, P3)
+ # P(t) = (1-t)²P1 + 2t(1-t)P2 + t²P3
+ #
+ # courbe bezier niveau 3 sur (P1, P2, P3, P4)
+ # P(t) = (1-t)³P1 + 3t(1-t)²P2 + 3t²(1-t)P3 + t³P4
+ #---------------------------------------------------------------------------
+ """
+ ncoords = len(coords)
+ if ncoords == 3:
+ (p1, c1, p2) = coords
+ c2 = None
+ elif ncoords == 4:
+ (p1, c1, c2, p2) = coords
+
+ # extrémités : points sur la courbe
+ #A VERIFIER
+ #Pas compris
+ if (not t):
+ return tuple(p1)
+ if (t >= 1.0):
+ return p2
+
+
+ t2 = t * t
+ t3 = t2 * t
+ pt = []
+
+ # calcul pour x et y
+ for i in (0, 1) :
+
+ if (c2) :
+ r1 = (1 - (3*t) + (3*t2) - t3) * p1[i]
+ r2 = ((3*t) - (6*t2) + (3*t3)) * c1[i]
+ r3 = ((3*t2) - (3*t3)) * c2[i]
+ r4 = (t3) * p2[i]
+
+ pt[i] = (r1 + r2 + r3 + r4)
+
+ else :
+ r1 = (1 - (2*t) + t2) * p1[i]
+ r2 = ((2*t) - (2*t2)) * c1[i]
+ r3 = (t2) * p2[i]
+
+ pt[i] = (r1 + r2 + r3)
+
+ return tuple(pt)
+
+def bezier_compute(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::bezier_compute
+ # Retourne une liste de coordonnées décrivant un segment de bezier
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste des points définissant le segment
+ # de bezier
+ #
+ # options :
+ # -precision : <dimension> seuil limite du calcul d'approche de la courbe
+ # -skipend : <boolean> : ne pas retourner le dernier point du segment
+ # (chaînage bezier)
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('precision')) :
+ precision = options['precision']
+ else:
+ precision = bezierClosenessThreshold
+ lastit = []
+
+ subdivide_bezier(coords, lastit, precision)
+
+ if (not options.has_key('skipend') or not options['skipend']):
+ lastit.append(coords[3])
+
+ return lastit
+
+def smallenough_bezier(bezier, precision):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::smallEnought
+ # intégration code Stéphane Conversy : calcul points bezier
+ # (précision auto ajustée)
+ #---------------------------------------------------------------------------
+ # distance is something like num/den with den=sqrt(something)
+ # what we want is to test that distance is smaller than precision,
+ # so we have distance < precision ? eq. to distance^2 < precision^2 ?
+ # eq. to (num^2/something) < precision^2 ?
+ # eq. to num^2 < precision^2*something
+ # be careful with huge values though (hence 'long long')
+ # with common values: 9add 9mul
+ #---------------------------------------------------------------------------
+ """
+ (pt_x, pt_y) = (0, 1)
+ (a, b) = (bezier[0], bezier[3])
+
+ den = ((a[pt_y]-b[pt_y])*(a[pt_y]-b[pt_y])) + ((b[pt_x]-a[pt_x])*(b[pt_x]-a[pt_x]))
+ p = precision*precision
+
+ # compute distance between P1|P2 and P0|P3
+ mat = bezier[1]
+ num1 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x]))
+
+ mat = bezier[2]
+ num2 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x]))
+
+ # take the max
+ num1 = max(num1, num2)
+
+ if (p*den > (num1*num1)):
+ return 1
+ else:
+ return 0
+
+def subdivide_bezier(bezier, it, precision, integeropt):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::subdivide_bezier
+ # subdivision d'une courbe de bezier
+ #---------------------------------------------------------------------------
+ """
+ (b0, b1, b2, b3) = bezier
+
+ if (smallenough_bezier(bezier, precision)) :
+ it.append((b0[0], b0[1]))
+
+ else :
+ (left, right) = (None, None)
+
+ for i in (0, 1) :
+
+ if (integeropt) :
+ # int optimized (6+3=9)add + (5+3=8)shift
+
+ left[0][i] = b0[i]
+ left[1][i] = (b0[i] + b1[i]) >> 1
+ # keep precision
+ left[2][i] = (b0[i] + b2[i] + (b1[i] << 1)) >> 2
+
+ tmp = (b1[i] + b2[i])
+ left[3][i] = (b0[i] + b3[i] + (tmp << 1) + tmp) >> 3
+
+ right[3][i] = b3[i]
+ right[2][i] = (b3[i] + b2[i]) >> 1
+ # keep precision
+ right[1][i] = (b3[i] + b1[i] + (b2[i] << 1) ) >> 2
+ right[0][i] = left[3][i]
+
+ else :
+ # float
+
+ left[0][i] = b0[i]
+ left[1][i] = float(b0[i] + b1[i]) / 2
+ left[2][i] = float(b0[i] + (2*b1[i]) + b2[i]) / 4
+ left[3][i] = float(b0[i] + (3*b1[i]) + (3*b2[i]) + b3[i]) / 8
+
+ right[3][i] = b3[i]
+ right[2][i] = float(b3[i] + b2[i]) / 2
+ right[1][i] = float(b3[i] + (2*b2[i]) + b1[i]) / 4
+ right[0][i] = float(b3[i] + (3*b2[i]) + (3*b1[i]) + b0[i]) / 8
+
+
+
+ subdivide_bezier(left, it, precision, integeropt)
+ subdivide_bezier(right, it, precision, integeropt)
+
+
+#Local Variables:
+#mode : python
+#tab-width: 4
+#end:
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/graphics.py b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/graphics.py
new file mode 100755
index 0000000..5277e5c
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/graphics.py
@@ -0,0 +1,2351 @@
+# -*- coding: iso-8859-1 -*-
+"""
+#-------------------------------------------------------------------------------
+#
+# Graphics.py
+# some graphic design functions
+#
+#-------------------------------------------------------------------------------
+# Functions to create complexe graphic component :
+# ------------------------------------------------
+# build_zinc_item (realize a zinc item from description hash table
+# management of enhanced graphics functions)
+#
+# repeat_zinc_item (duplication of given zinc item)
+#
+# Function to compute complexe geometrical forms :
+# (text header of functions explain options for each form,
+# function return curve coords using control points of cubic curve)
+# -----------------------------------------------------------------
+# rounded_rectangle_coords (return curve coords of rounded rectangle)
+# hippodrome_coords (return curve coords of circus form)
+# ellipse_coords (return curve coords of ellipse form)
+# polygon_coords (return curve coords of regular polygon)
+# roundedcurve_coords (return curve coords of rounded curve)
+# polyline_coords (return curve coords of polyline)
+# shiftpath_coords (return curve coords of shifting path)
+# tabbox_coords (return curve coords of tabbox's pages)
+# pathline_coords (return triangles coords of pathline)
+#
+# Function to compute 2D 1/2 relief and shadow :
+# function build zinc items (triangles and curve) to simulate this
+# -----------------------------------------------------------------
+# graphicitem_relief (return triangle items simulate relief of given item)
+# polyline_relief_params (return triangle coords
+# and lighting triangles color list)
+# graphicitem_shadow (return triangles and curve items
+# simulate shadow of given item))
+# polyline_shadow_params (return triangle and curve coords
+# and shadow triangles color list))
+#
+#
+#-------------------------------------------------------------------------------
+# Authors: Jean-Luc Vinot <vinot@cena.fr>
+# PM2PY: Guillaume Vidon <vidon@ath.cena.fr>
+#
+# $Id: graphics.py 1697 2005-06-13 00:25:58Z vidon $
+#-------------------------------------------------------------------------------
+"""
+VERSION = "1.0"
+__revision__ = "0.1"
+
+import logging
+import types
+import re
+from geometry import *
+from pictorial import *
+from math import pi, radians, atan2, sqrt, sin, cos
+
+graphiclogger = logging.getLogger('Graphics')
+debug = graphiclogger.debug
+error = graphiclogger.error
+exception = graphiclogger.exception
+log = lambda msg : graphiclogger.log(logging.DEBUG, msg)
+
+# constante facteur point directeur (conique -> quadratique)
+const_ptd_factor = .5523
+
+def transdic(**dict):
+ newdic={}
+ for key, val in dict.items():
+ if (type(val) is types.ListType):
+ newdic[key] = tuple(val)
+ else:
+ newdic[key] = val
+ return newdic
+
+def is_flat_list(apts):
+ if reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
+ apts):
+ if len(apts) % 2:
+ raise ValueError("Not a valid Coords list")
+ else :
+ return True
+ else :
+ return False
+
+def is_point(apoint):
+ if (type(apoint) in ( types.TupleType, types.ListType)):
+ if len(apoint) == 2 :
+ if reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
+ apts):
+ return True
+ else :
+ return False
+ elif reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
+ apts[:-1])\
+ and type(apts[-1]) in ('c', 'n'):
+ return True
+ else :
+ return False
+ else :
+ return False
+
+# def is_tuple_list(apts):
+# if reduce(lambda x, y : x \
+# and is_point(x)),
+# apts):
+
+
+def lpts2coords(lpts):
+ coords = []
+ if (type(lpts) in ( types.TupleType, types.ListType )):
+ for point in lpts :
+ coords.append(tuple(point))
+ return tuple(coords)
+
+def coords2lpts(coords):
+ lpts = []
+ if (type(coords) in ( types.TupleType, types.ListType )):
+ for point in coords :
+ lpts.append(list(point))
+ else :
+ raise ValueError("Invalid Coords %s "%coords)
+ return lpts
+
+def build_zinc_item(widget, pgroup = 1, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::build_zinc_item
+ # Création d'un objet Zinc de représentation
+ #---------------------------------------------------------------------------
+ # types d'items valides :
+ # les items natifs zinc : group, rectangle, arc, curve, text, icon
+ # les items ci-après permettent de spécifier des curves 'particulières' :
+ # -roundedrectangle : rectangle à coin arrondi
+ # -hippodrome : hippodrome
+ # -ellipse : ellipse un centre 2 rayons
+ # -polygone : polygone régulier à n cotés (convexe ou en étoile)
+ # -roundedcurve : curve multicontours à coins arrondis (rayon unique)
+ # -polyline : curve multicontours à coins arrondis (le rayon pouvant
+ # être défini
+ # spécifiquement pour chaque sommet)
+ # -pathline : création d'une ligne 'épaisse' avec l'item Zinc
+ # triangles décalage par rapport à un chemin donné
+ # (largeur et sens de décalage)
+ # dégradé de couleurs de la ligne (linéaire, transversal
+ # ou double)
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget Zinc
+ # parentgroup : <tagOrId> identifiant du group parent
+ #
+ # options :
+ # -itemtype : type de l'item à construire (type zinc ou metatype)
+ # -coords : <coords|coordsList> coordonnées de l'item
+ # -metacoords : <hastable> calcul de coordonnées par type
+ # d'item différent de itemtype
+ # -contours : <contourList> paramètres multi-contours
+ # -params : <hastable> arguments spécifiques de l'item à passer
+ # au widget
+ # -addtags : [list of specific tags] to add to params -tags
+ # -texture : <imagefile> ajout d'une texture à l'item
+ # -pattern : <imagefile> ajout d'un pattern à l'item
+ # -relief : <hastable> création d'un relief à l'item invoque la fonction
+ # graphicitem_relief()
+ # -shadow : <hastable> création d'une ombre portée à l'item invoque
+ # la fonction graphicitem_shadow()
+ # -scale : <scale_factor|[xscale_factor,yscale_factor]> application
+ # d'une transformation zinc->scale à l'item
+ # -translate : <[delta_x,delta_y]> application d'un transformation zinc->translate
+ # à l'item.
+ # -rotate : <angle> application d'une transformation zinc->rotate
+ # (en degré) à l'item
+ # -name : <str> nom de l'item
+ # spécifiques item group :
+ # -clip : <coordList|hashtable> paramètres de clipping d'un item group
+ # (coords ou item)
+ # -items : <hashtable> appel récursif de la fonction permettant
+ # d'inclure des items au groupe
+ #---------------------------------------------------------------------------
+ #
+ #---------------------------------------------------------------------------
+ """
+
+ if options.has_key('parentgroup'):
+ parentgroup = options['parentgroup']
+ else :
+ parentgroup = pgroup
+ try:
+ itemtype = options['itemtype']
+ except KeyError:
+ raise ValueError("Must have itemtype option")
+ try:
+ coords = options['coords']
+ except KeyError:
+ try:
+ coords = options['metacoords']
+ except KeyError :
+ raise ValueError("Must have coords or metacoords option")
+
+ if options.has_key('params'):
+ params = options['params']
+ else:
+ params = {}
+
+ #return unless($widget and $itemtype
+ #and ($coords or $options{'-metacoords'}))
+
+ try:
+ name = options['name']
+ except KeyError:
+ name = None
+
+ item = None
+ metatype = None
+ items = []
+ reliefs = []
+ shadows = []
+ tags = []
+
+ #--------------------
+ # GEOMETRIE DES ITEMS
+
+ # gestion des types d'items particuliers et à raccords circulaires
+ if (itemtype in ( 'roundedrectangle',
+ 'hippodrome',
+ 'polygone',
+ 'ellipse',
+ 'roundedcurve',
+ 'polyline',
+ 'curveline')):
+
+ # par défaut la curve sera fermée -closed = 1
+ if not params.has_key('closed'):
+ params['closed'] = 1
+ metatype = itemtype
+ itemtype = 'curve'
+
+ # possibilité de définir les coordonnées initiales par metatype
+ if (options.has_key('metacoords')) :
+ options['coords'] = meta_coords( **options['metacoords'])
+
+ # création d'une pathline à partir d'item zinc triangles
+ elif (itemtype == 'pathline') :
+ itemtype = 'triangles'
+ if (options.has_key('metacoords')) :
+ coords = meta_coords( **options['metacoords'])
+
+ if (options.has_key('graduate')) :
+ numcolors = len(coords)
+ lcolors = path_graduate(widget,
+ numcolors,
+ options['graduate'])
+ params['colors'] = tuple(lcolors)
+
+ if options.has_key('coords'):
+ coords = pathline_coords(**options)
+ else:
+ coords = pathline_coords(coords, **options)
+
+ # création d'une boite à onglet
+ elif (itemtype == 'tabbox') :
+ return build_tabboxitem(widget, parentgroup, **options)
+
+ # calcul des coordonnées finales de la curve
+ if (metatype is not None):
+ coords = meta_coords(type = metatype, **options)
+
+
+ # gestion du multi-contours (accessible pour tous les types
+ # d'items géometriques)
+ if (options.has_key('contours') and (metatype is not None)) :
+ lcontours = options['contours']
+ contours=[]
+ numcontours = len(contours)
+ for contour in lcontours:
+ # radius et corners peuvent être défini
+ # spécifiquement pour chaque contour
+ (atype, way, addcoords,) = contour[:3]
+ if len(contour) >= 4:
+ radius = contour[3]
+ else :
+ radius = None
+ if len(contour) >= 5:
+ corners = contour[4]
+ else:
+ corners = None
+ if len(contour) >= 6:
+ corners_radius = contour[5]
+ else :
+ corners_radius = None
+ if (radius is None):
+ if options.has_key('radius'):
+ radius = options['radius']
+ else :
+ raise ValueError("radius option requiered")
+
+ newcoords = meta_coords(type = metatype,
+ coords = addcoords,
+ radius = radius,
+ corners = corners,
+ corners_radius = corners_radius
+ )
+ contours.append((atype, way, newcoords))
+
+ options['contours'] = contours
+
+ #----------------------
+ # REALISATION DES ITEMS
+
+ # ITEM GROUP
+ # gestion des coordonnées et du clipping
+ if (itemtype == 'group') :
+ item = widget.add(itemtype,
+ parentgroup,
+ **params)
+ widget.addtag_withtag(name, item)
+ if coords:
+ widget.coords(item, tuple(coords))
+
+ # clipping du groupe par item ou par géometrie
+ if (options.has_key('clip')) :
+ clipbuilder = options['clip']
+ clip = None
+
+ # création d'un item de clipping
+ if (type(clipbuilder) is types.DictType
+ and clipbuilder.has_key('itemtype')):
+ clip = build_zinc_item(widget, item, **clipbuilder)
+
+ elif (type(clipbuilder) in (types.TupleType, types.ListType)
+ or widget.type(clipbuilder)) :
+ clip = clipbuilder
+
+ if (clip):
+ widget.itemconfigure(item, clip = clip)
+
+ # créations si besoin des items contenus dans le groupe
+ if (options.has_key('items')
+ and type(options['items']) is types.DictType) :
+ for (itemname, itemstyle) in options['items'].items() :
+ if not itemstyle.has_key('name'):
+ itemstyle['name'] = itemname
+ build_zinc_item(widget, item, **itemstyle)
+
+
+ # ITEM TEXT ou ICON
+ elif (itemtype in ('text', 'icon')) :
+ imagefile = None
+ if (itemtype == 'icon') :
+ imagefile = params['image']
+ image = get_image(widget, imagefile)
+ if (image) :
+ params['image'] = image
+ else:
+ params['image'] = ""
+
+
+ item = widget.add(itemtype,
+ parentgroup,
+ position = coords,
+ **params
+ )
+ if imagefile:
+ params['image'] = imagefile
+
+
+ # ITEMS GEOMETRIQUES -> CURVE
+ else :
+ nparams=params
+ item = widget.add(itemtype,
+ parentgroup,
+ lpts2coords(coords),
+ **params
+ )
+
+ if (itemtype == 'curve' and options.has_key('contours')) :
+ for contour in options['contours'] :
+ contour = list(contour)
+ contour[2] = tuple(contour[2])
+ widget.contour(item, *contour)
+
+ # gestion du mode norender
+ if (options.has_key('texture')) :
+ texture = get_texture(widget, options['texture'])
+ if texture:
+ widget.itemconfigure(item, tile = texture)
+
+ if (options.has_key('pattern')) :
+ bitmap = get_pattern(**options['pattern'])
+ if bitmap:
+ widget.itemconfigure(item, fillpattern = bitmap)
+
+ # gestion des tags spécifiques
+ if (options.has_key('addtags')) :
+ tags = options['addtags']
+
+ params_tags = params['tags']
+ if params_tags:
+ tags.extend(params_tags)
+
+ widget.itemconfigure(item, tags = tags)
+
+ #-------------------------------
+ # TRANSFORMATIONS ZINC DE L'ITEM
+
+ # transformation scale de l'item si nécessaire
+ if (options.has_key('scale')) :
+ scale = options['scale']
+ if (type(scale) is not types.TupleType) :
+ scale = (scale, scale)
+ widget.scale(item, scale)
+
+
+ # transformation rotate de l'item si nécessaire
+ if (options.has_key('rotate')):
+ widget.rotate(item, radians(options['rotate']))
+
+ # transformation translate de l'item si nécessaire
+ if (options.has_key('translate')):
+ widget.translate(item, options['translate'])
+
+
+ # répétition de l'item
+ if (options.has_key('repeat')) :
+ items.extend((item,
+ repeat_zinc_item(widget, item, **options['repeat'])))
+
+ #-----------------------
+ # RELIEF ET OMBRE PORTEE
+
+ # gestion du relief
+ if (options.has_key('relief')) :
+ if (len(items)) :
+ target = items
+ else:
+ target = item
+ reliefs.extend(graphicitem_relief(widget,
+ target, **options['relief']))
+
+ # gestion de l'ombre portée
+ if (options.has_key('shadow')) :
+ if (len(items)) :
+ target = items
+ else:
+ target = item
+ shadows.extend(graphicitem_shadow(widget,
+ target, **options['shadow']))
+
+
+ if len(reliefs):
+ items.extend(reliefs)
+ if len(shadows):
+ items.extend(shadows)
+
+ if len(items):
+ return items
+ else:
+ return item
+
+def repeat_zinc_item(widget,
+ item,
+ num = 2,
+ dxy = (0,0),
+ angle = None,
+ params = None,
+ copytag = None) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::repeat_zinc_item
+ # Duplication (clonage) d'un objet Zinc de représentation
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # item : <tagOrId> identifiant de l'item source
+ # options :
+ # -num : <n> nombre d'item total (par defaut 2)
+ # -dxy : <[delta_x, delta_y]> translation entre 2 duplications (par defaut [0,0])
+ # -angle : <angle> rotation entre 2 duplications
+ # -copytag : <sting> ajout d'un tag indexé pour chaque copie
+ # -params : <hashtable> {clef => [value list]}> valeur de paramètre
+ # de chaque copie
+ #---------------------------------------------------------------------------
+ """
+ clones = []
+ delta_x, delta_y = dxy
+ # duplication d'une liste d'items -> appel récursif
+ if (type(item) in (types.TupleType, types.ListType)) :
+ for part in item :
+ clones.append(repeat_zinc_item(widget,
+ part,
+ dxy,
+ angle,
+ params,
+ copytag))
+
+ return clones
+
+ tags = []
+
+ if (copytag) :
+ tags = widget.itemcget(item, 'tags')
+ widget.itemconfigure(item, tags = tags + ("%s0"%copytag,))
+
+ for i in xrange(1, num) :
+ clone = None
+
+ if (copytag) :
+ clone = widget.clone(item, tags = tags + ("%s%s"%(copytag, i),))
+ else :
+ clone = widget.clone(item)
+
+ clones.append(clone)
+ widget.translate(clone, delta_x*i, delta_y*i)
+ if angle :
+ widget.rotate(clone, radians(angle*i))
+
+ if (params is not None ) :
+ widget.itemconfigure(clone, **params )
+ return clones
+
+
+#MUST BE TESTED
+def meta_coords( type,
+ coords,
+ **options ):
+ """
+ #---------------------------------------------------------------------------
+ # FONCTIONS GEOMETRIQUES
+ #---------------------------------------------------------------------------
+
+ #---------------------------------------------------------------------------
+ # Graphics::meta_coords
+ # retourne une liste de coordonnées en utilisant la fonction du type
+ # d'item spécifié
+ #---------------------------------------------------------------------------
+ # paramètres : (passés par %options)
+ # -type : <string> type de primitive utilisée
+ # -coords : <coordsList> coordonnées nécessitée par la fonction [type]_coords
+ #
+ # les autres options spécialisées au type seront passés
+ # à la fonction [type]coords
+ #---------------------------------------------------------------------------
+ """
+ pts = None
+
+ if (type == 'roundedrectangle'):
+ log('Coords for roundedrectangle')
+ pts = rounded_rectangle_coords(coords, **options)
+
+ elif (type == 'hippodrome') :
+ log('Coords for hippodrome')
+ pts = hippodrome_coords(coords, **options)
+
+ elif (type == 'ellipse') :
+ log('Coords for ellipse')
+ pts = ellipse_coords(coords, **options)
+
+ elif (type == 'roundedcurve') :
+ log('Coords for roundedcurve')
+ pts = roundedcurve_coords(coords, **options)
+
+ elif (type == 'polygone') :
+ log('Coords for polygone')
+ pts = polygon_coords(coords, **options)
+
+ elif (type == 'polyline') :
+ log('Coords for polyline')
+ pts = polyline_coords(coords, **options)
+
+ elif (type == 'curveline') :
+ log('Coords for curveline')
+ pts = curveline_coords(coords, **options)
+
+ return pts
+
+
+def zincitem_2_curvecoords( widget, item,
+ linear = 0,
+ realcoords = 0,
+ adjust = 1,
+ ):
+ """
+ #--------------------------------------------------------------------------
+ # Graphics::zincitem_2_curvecoords
+ # retourne une liste des coordonnées 'Curve' d'un l'item Zinc
+ # rectangle, arc ou curve
+ #--------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # item : <tagOrId> identifiant de l'item source
+ # options :
+ # -linear : <boolean> réduction à des segments non curviligne
+ # (par défaut 0)
+ # -realcoords : <boolean> coordonnées à transformer dans le groupe père
+ # (par défaut 0)
+ # -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
+ #--------------------------------------------------------------------------
+ """
+ itemtype = widget.type(item)
+
+ if not itemtype :
+ raise ValueError("Not a Valid Item %s" % item)
+
+ itemcoords = widget.coords(item)
+ coords = None
+ multi = []
+
+ if (itemtype == 'rectangle') :
+ coords = rounded_rectangle_coords(itemcoords, radius = 0)
+
+ elif (itemtype == 'arc') :
+ coords = ellipse_coords(itemcoords)
+ if linear :
+ coords = curve2polyline_coords(coords, adjust)
+
+ elif (itemtype == 'curve') :
+ numcontours = widget.contour(item)
+
+ if (numcontours < 2) :
+ if linear:
+ coords = curve2polyline_coords(itemcoords, adjust)
+ else :
+ if (linear) :
+ multi = curveitem2polyline_coords(widget, item)
+
+ else :
+ for contour in xrange(0, numcontours):
+ points = widget.coords(item, contour)
+ multi.extend(points)
+ coords = multi
+
+ if (realcoords) :
+ parentgroup = widget.group(item)
+ if (len(multi)) :
+ newcoords = []
+ for points in multi :
+ transcoords = widget.transform(item, parentgroup, points)
+ newcoords.extend(transcoords)
+ coords = newcoords
+ else :
+ transcoords = widget.transform(item, parentgroup, coords)
+ coords = transcoords
+
+ return coords
+
+def rounded_rectangle_coords( coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rounded_rectangle_coords
+ # calcul des coords du rectangle à coins arrondis
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> coordonnées bbox (haut-gauche et bas-droite)
+ # du rectangle
+ # options :
+ # -radius : <dimension> rayon de raccord d'angle
+ # -corners : <booleanList> liste des raccords de sommets
+ # [0 (aucun raccord)|1] par défaut [1,1,1,1]
+ #---------------------------------------------------------------------------
+ """
+ (x_0, y_0, x_n, y_n) = (coords[0][0], coords[0][1],
+ coords[1][0], coords[1][1])
+
+ if (options.has_key('radius')):
+ radius = options['radius']
+ else:
+ radius = None
+
+ if (options.has_key('corners')):
+ corners = options['corners']
+ else:
+ corners = [1, 1, 1, 1]
+
+ # attention aux formes 'négatives'
+ if (x_n < x_0) :
+ (x_0, x_n) = (x_n, x_0)
+
+ if (y_n < y_0) :
+ (y_0, y_n) = (y_n, y_0)
+
+ height = min(x_n -x_0, y_n - y_0)
+ #radius non defini dans les parametres
+ if (radius is None) :
+ radius = int(height/10)
+ radius = max(radius, 3)
+
+ #radius defini mais trop petit
+ if ( radius < 2) :
+ return ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))
+
+ # correction de radius si necessaire
+ max_rad = height
+ #CODE BIZARRE
+ #Comment corners ne peut être non défini
+ #a ce niveau ?
+ # max_rad /= 2 if (!defined corners)
+ if (corners is None):
+ max_rad /= 2
+ radius = min(max_rad, radius)
+
+ # points remarquables
+ ptd_delta = radius * const_ptd_factor
+ (x_2, x_3) = (x_0 + radius, x_n - radius)
+ (x_1, x_4) = (x_2 - ptd_delta, x_3 + ptd_delta)
+ (y_2, y_3) = (y_0 + radius, y_n - radius)
+ (y_1, y_4) = (y_2 - ptd_delta, y_3 + ptd_delta)
+
+ # liste des 4 points sommet du rectangle : angles sans raccord circulaire
+ angle_pts = ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))
+
+ # liste des 4 segments quadratique : raccord d'angle = radius
+ roundeds = [[(x_2, y_0), (x_1, y_0, 'c'), (x_0, y_1, 'c'), (x_0, y_2),],
+ [(x_0, y_3), (x_0, y_4, 'c'), (x_1, y_n, 'c'), (x_2, y_n),],
+ [(x_3, y_n), (x_4, y_n, 'c'), (x_n, y_4, 'c'), (x_n, y_3),],
+ [(x_n, y_2), (x_n, y_1, 'c'), (x_4, y_0, 'c'), (x_3, y_0),]]
+
+ pts = []
+ previous = None
+ for i in xrange(0, 4):
+ #BUGS ??
+ if (corners[i]):
+ if (previous is not None) :
+ # on teste si non duplication de point
+ (nx, ny) = roundeds[i][0]
+ if (previous[0] == nx and previous[1] == ny) :
+ pts.pop()
+ pts.extend(roundeds[i])
+ previous = roundeds[i][3]
+ else :
+ pts.append(angle_pts[i])
+
+ return pts
+
+def ellipse_coords(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::ellipse_coords
+ # calcul des coords d'une ellipse
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> coordonnées bbox du rectangle exinscrit
+ # options :
+ # -corners : <booleanList> liste des raccords de sommets
+ # [0 (aucun raccord)|1] par défaut [1,1,1,1]
+ #---------------------------------------------------------------------------
+ """
+ (x_0, y_0, x_n, y_n) = (coords[0][0], coords[0][1],
+ coords[1][0], coords[1][1])
+
+ if options.has_key('corners') :
+ corners = options.has_key('corners')
+ else:
+ corners = [1, 1, 1, 1]
+
+ # attention aux formes 'négatives'
+ if (x_n < x_0) :
+ xs = x_0
+ (x_0, x_n) = (x_n, xs)
+ if (y_n < y_0) :
+ ys = y_0
+ (y_0, y_n) = (y_n, ys)
+
+ # points remarquables
+ delta_x = (x_n - x_0)/2 * const_ptd_factor
+ delta_y = (y_n - y_0)/2 * const_ptd_factor
+ (x_2, y_2) = ((x_0+x_n)/2, (y_0+y_n)/2)
+ (x_1, x_3) = (x_2 - delta_x, x_2 + delta_x)
+ (y_1, y_3) = (y_2 - delta_y, y_2 + delta_y)
+
+ # liste des 4 points sommet de l'ellipse : angles sans raccord circulaire
+ angle_pts = ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))
+
+ # liste des 4 segments quadratique : raccord d'angle = arc d'ellipse
+ roundeds = (((x_2, y_0), (x_1, y_0, 'c'), (x_0, y_1, 'c'), (x_0, y_2), ),
+ ((x_0, y_2), (x_0, y_3, 'c'), (x_1, y_n, 'c'), (x_2, y_n), ),
+ ((x_2, y_n), (x_3, y_n, 'c'), (x_n, y_3, 'c'), (x_n, y_2), ),
+ ((x_n, y_2), (x_n, y_1, 'c'), (x_3, y_0, 'c'), (x_2, y_0), ))
+
+ pts = []
+ previous = None
+ for i in xrange(0, 4):
+ if (corners[i]) :
+ if (previous) :
+ # on teste si non duplication de point
+ (nx, ny) = roundeds[i][0]
+ if (previous[0] == nx and previous[1] == ny) :
+ pts.pop()
+
+
+ pts.extend(roundeds[i])
+ previous = roundeds[i][3]
+
+ else :
+ pts.append(angle_pts[i])
+
+ return pts
+
+
+def hippodrome_coords(coords, **options) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::hippodrome_coords
+ # calcul des coords d'un hippodrome
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> coordonnées bbox du rectangle exinscrit
+ # options :
+ # -orientation : orientation forcée de l'hippodrome [horizontal|vertical]
+ # -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
+ # -trunc : troncatures [left|right|top|bottom|both]
+ #---------------------------------------------------------------------------
+ """
+ (x_0, y_0, x_n, y_n) = (coords[0][0],
+ coords[0][1],
+ coords[1][0],
+ coords[1][1])
+
+ if (options.has_key('orientation')) :
+ orientation = options['orientation']
+ else:
+ orientation = 'none'
+
+ # orientation forcée de l'hippodrome
+ # (sinon hippodrome sur le plus petit coté)
+ if (orientation == 'horizontal') :
+ height = abs(y_n - y_0)
+ elif (orientation == 'vertical') :
+ height = abs(x_n - x_0)
+ else:
+ height = min(abs(x_n - x_0), abs(y_n - y_0))
+ radius = height/2
+ corners = (1, 1, 1, 1)
+
+ if (options.has_key('corners')) :
+ corners = options['corners']
+
+ elif (options.has_key('trunc')) :
+ trunc = options['trunc']
+ if (trunc == 'both') :
+ return ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))
+ else :
+ if (trunc == 'left'):
+ corners = (0, 0, 1, 1)
+ elif (trunc == 'right'):
+ corners = (1, 1, 0, 0)
+ elif (trunc == 'top'):
+ corners = (0, 1, 1, 0)
+ elif (trunc == 'bottom') :
+ corners = (1, 0, 0, 1)
+ else :
+ corners = (1, 1, 1, 1)
+
+ # l'hippodrome est un cas particulier de roundedRectangle
+ # on retourne en passant la 'configuration' à la fonction
+ # générique rounded_rectangle_coords
+ return rounded_rectangle_coords(coords,
+ radius = radius,
+ corners = corners)
+
+def polygon_coords(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::polygon_coords
+ # calcul des coords d'un polygone régulier
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coords> point centre du polygone
+ # options :
+ # -numsides : <integer> nombre de cotés
+ # -radius : <dimension> rayon de définition du polygone
+ # (distance centre-sommets)
+ # -inner_radius : <dimension> rayon interne (polygone type étoile)
+ # -corners : <booleanList> liste des raccords de sommets [0|1]
+ # par défaut [1,1,1,1]
+ # -corner_radius : <dimension> rayon de raccord des cotés
+ # -startangle : <angle> angle de départ en degré du polygone
+ #---------------------------------------------------------------------------
+ """
+ if options.has_key('numsides'):
+ numsides = options['numsides']
+ else :
+ numsides = 0
+ if options.has_key('radius'):
+ radius = options['radius']
+ else:
+ radius = None
+ if (numsides < 3 or not radius) :
+ raise ValueError("Vous devez au moins spécifier "
+ +"un nombre de cotés >= 3 et un rayon...\n")
+
+ if (coords is None):
+ coords = (0, 0)
+ if (options.has_key('startangle')) :
+ startangle = options['startangle']
+ else:
+ startangle = 0
+ anglestep = 360/numsides
+ if options.has_key('inner_radius'):
+ inner_radius = options['inner_radius']
+ else:
+ inner_radius = None
+ pts = []
+
+ # points du polygone
+ for i in xrange(0, numsides):
+ (xp, yp) = rad_point(coords, radius, startangle + (anglestep*i))
+ pts.append((xp, yp))
+
+ # polygones 'étoiles'
+ if (inner_radius) :
+ (xp, yp) = rad_point(coords, inner_radius,
+ startangle + (anglestep*(i+ 0.5)))
+ pts.append((xp, yp))
+
+ pts.reverse()
+
+ if (options.has_key('corner_radius')) :
+ if options.has_key('corners'):
+ corners = options['corners']
+ else:
+ corners = None
+ return roundedcurve_coords(pts,
+ radius = options['corner_radius'],
+ corners = corners)
+ else :
+ return pts
+
+
+def rounded_angle(widget, parentgroup, coords, radius) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rounded_angle
+ # THIS FUNCTION IS NO MORE USED, NEITHER EXPORTED
+ # curve d'angle avec raccord circulaire
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : identifiant du widget Zinc
+ # parentgroup : <tagOrId> identifiant de l'item group parent
+ # coords : <coordsList> les 3 points de l'angle
+ # radius : <dimension> rayon de raccord
+ #---------------------------------------------------------------------------
+ """
+ (pt0, pt1, pt2) = coords
+
+ (corner_pts, center_pts) = rounded_angle_coords(coords, radius)
+ (cx_0, cy_0) = center_pts
+
+ if (parentgroup is None) :
+ parentgroup = 1
+
+ pts = [pt0]
+ pts.extend(corner_pts)
+ pts.append(pt2)
+
+ widget.add('curve',
+ parentgroup,
+ lpts2coords(pts),
+ closed = 0,
+ linewidth = 1,
+ priority = 20,
+ )
+
+
+def rounded_angle_coords (coords, radius) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rounded_angle_coords
+ # calcul des coords d'un raccord d'angle circulaire
+ #---------------------------------------------------------------------------
+ # le raccord circulaire de 2 droites sécantes est traditionnellement
+ # réalisé par un
+ # arc (conique) du cercle inscrit de rayon radius tangent à ces 2 droites
+ #
+ # Quadratique :
+ # une approche de cette courbe peut être réalisée simplement par le calcul
+ # de 4 points
+ # spécifiques qui définiront - quelle que soit la valeur de l'angle formé
+ # par les 2
+ # droites - le segment de raccord :
+ # - les 2 points de tangence au cercle inscrit seront les points de début
+ # et de fin
+ # du segment de raccord
+ # - les 2 points de controle seront situés chacun sur le vecteur
+ # reliant le point de
+ # tangence au sommet de l'angle (point secant des 2 droites)
+ # leur position sur ce vecteur peut être simplifiée comme suit :
+ # - à un facteur de 0.5523 de la distance au sommet pour
+ # un angle >= 90° et <= 270°
+ # - à une 'réduction' de ce point vers le point de tangence
+ # pour les angles limites
+ # de 90° vers 0° et de 270° vers 360°
+ # ce facteur sera légérement modulé pour recouvrir plus précisement
+ # l'arc correspondant
+ #---------------------------------------------------------------------------
+ # coords : <coordsList> les 3 points de l'angle
+ # radius : <dimension> rayon de raccord
+ #---------------------------------------------------------------------------
+ """
+ (pt0, pt1, pt2) = coords
+
+ # valeur d'angle et angle formé par la bisectrice
+ (angle, bisecangle) = vertex_angle(pt0, pt1, pt2)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+
+ if (asin) :
+ delta = abs(radius / asin)
+ else:
+ delta = radius
+
+ # point centre du cercle inscrit de rayon $radius
+ if (angle < 180) :
+ refangle = bisecangle + 90
+ else :
+ refangle = bisecangle - 90
+
+ (cx_0, cy_0) = rad_point(pt1, delta, refangle)
+
+ # points de tangeance : pts perpendiculaires du centre aux 2 droites
+ (px_1, py_1) = perpendicular_point((cx_0, cy_0), (pt0, pt1))
+ (px_2, py_2) = perpendicular_point((cx_0, cy_0), (pt1, pt2))
+
+ # point de controle de la quadratique
+ # facteur de positionnement sur le vecteur pt.tangence, sommet
+ ptd_factor = const_ptd_factor
+ if (angle < 90 or angle > 270) :
+ if (angle < 90) :
+ diffangle = angle
+ else:
+ diffangle = 360 - angle
+ if (diffangle > 15) :
+ ptd_factor -= (((90 - diffangle)/90) * (ptd_factor/4))
+ ptd_factor = (diffangle/90) * (ptd_factor
+ + ((1 - ptd_factor)
+ * (90 - diffangle)/90))
+ else :
+ diffangle = abs(180 - angle)
+ if (diffangle > 15) :
+ ptd_factor += (((90 - diffangle)/90) * (ptd_factor/3))
+
+ # delta xy aux pts de tangence
+ (d1x, d1y) = ((pt1[0] - px_1) * ptd_factor, (pt1[1] - py_1) * ptd_factor)
+ (d2x, d2y) = ((pt1[0] - px_2) * ptd_factor, (pt1[1] - py_2) * ptd_factor)
+
+ # les 4 points de l'arc 'quadratique'
+ corner_pts = [(px_1, py_1), (px_1+d1x, py_1+d1y, 'c'),
+ (px_2+d2x, py_2+d2y, 'c'), (px_2, py_2)]
+
+
+ # retourne le segment de quadratique et le centre du cercle inscrit
+ return (corner_pts, (cx_0, cy_0))
+
+
+def roundedcurve_coords(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::roundedcurve_coords
+ # retourne les coordonnées d'une curve à coins arrondis
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste de coordonnées des points de la curve
+ # options :
+ # -radius : <dimension> rayon de raccord d'angle
+ # -corners : <booleanList> liste des raccords de sommets [0|1]
+ # par défaut [1,1,1,1]
+ #---------------------------------------------------------------------------
+ """
+ numfaces = len(coords)
+ curve_pts = []
+
+ if (options.has_key('radius')) :
+ radius = options['radius']
+ else:
+ radius = 0
+ corners = None
+ if options.has_key('corners') :
+ corners = options['corners']
+
+ for index in xrange(numfaces):
+ if (corners is not None) :
+ if (index+1 > len(corners)) or not corners[index] :
+ curve_pts.append(coords[index])
+ continue
+
+ if (index) :
+ prev = index - 1
+ else :
+ prev = numfaces - 1
+ if (index > numfaces - 2) :
+ next = 0
+ else :
+ next = index + 1
+ anglecoords = (coords[prev], coords[index], coords[next])
+
+ quad_pts = rounded_angle_coords(anglecoords, radius)[0]
+ curve_pts.extend(quad_pts)
+ return curve_pts
+
+
+def polyline_coords(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::polyline_coords
+ # retourne les coordonnées d'une polyline
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste de coordonnées des sommets de la polyline
+ # options :
+ # -radius : <dimension> rayon global de raccord d'angle
+ # -corners : <booleanList> liste des raccords de sommets [0|1]
+ # par défaut [1,1,1,1],
+ # -corners_radius : <dimensionList> liste des rayons de raccords de sommets
+ #---------------------------------------------------------------------------
+ """
+ numfaces = len(coords)
+ curve_pts = []
+
+ if (options.has_key('radius')) :
+ radius = options['radius']
+ else:
+ radius = 0
+ if options.has_key('corners_radius'):
+ corners_radius = options['corners_radius']
+ corners = corners_radius
+ else:
+ corners_radius = None
+ if options.has_key('corners'):
+ corners = options['corners']
+ else:
+ corners = None
+
+ for index in xrange(0, numfaces):
+ if (corners is not None
+ and (len(corners) - 1 < index
+ or not corners[index])):
+ curve_pts.append(coords[index])
+ else :
+ if (index) :
+ prev = index - 1
+ else:
+ prev = numfaces - 1
+ if (index > numfaces - 2) :
+ next = 0
+ else:
+ next = index + 1
+ anglecoords = (coords[prev], coords[index], coords[next])
+
+ if (corners_radius) :
+ rad = corners_radius[index]
+ else:
+ rad = radius
+ quad_pts = rounded_angle_coords(anglecoords, rad)[0]
+ curve_pts.extend(quad_pts)
+
+ return curve_pts
+
+def pathline_coords (coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::pathline_coords
+ # retourne les coordonnées d'une pathline
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste de coordonnées des points du path
+ # options :
+ # -closed : <boolean> ligne fermée
+ # -shifting : <out|center|in> sens de décalage du path (par défaut center)
+ # -linewidth : <dimension> epaisseur de la ligne
+ #---------------------------------------------------------------------------
+ """
+ numfaces = len(coords)
+ pts = []
+
+ if options.has_key('closed'):
+ closed = options['closed']
+ else:
+ closed = None
+ if (options.has_key('linewidth')) :
+ linewidth = options['linewidth']
+ else:
+ linewidth = 2
+
+ if (options.has_key('shifting')) :
+ shifting = options['shifting']
+ else:
+ shifting = 'center'
+
+ if ( not numfaces or linewidth < 2):
+ raise ValueError("Invalid PathLine_coords")
+
+ if (closed) :
+ previous = coords[numfaces - 1]
+ else:
+ previous = None
+
+ next = coords[1]
+ if (shifting == 'center'):
+ linewidth /= 2
+
+ for i in xrange(0, numfaces):
+ pt = coords[i]
+
+ if (previous is None) :
+ # extrémité de curve sans raccord -> angle plat
+ previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
+
+ (angle, bisecangle) = vertex_angle(previous, pt, next)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+ if (asin) :
+ delta = abs(linewidth / asin)
+ else:
+ delta = linewidth
+
+ if (shifting == 'out' or shifting == 'in') :
+ if (shifting == 'out') :
+ adding = -90
+ else:
+ adding = 90
+ pts.append(rad_point(pt, delta, bisecangle + adding))
+ pts.append(pt)
+
+ else :
+ pts.append(rad_point(pt, delta, bisecangle-90))
+ pts.append(rad_point(pt, delta, bisecangle+90))
+
+ if (i == numfaces - 2) :
+ if (closed) :
+ next = coords[0]
+ else:
+ next = (coords[i+1][0] + (coords[i+1][0] - pt[0]),
+ coords[i+1][1] + (coords[i+1][1] - pt[1]))
+ elif (i == numfaces - 1):
+ next = None
+ else :
+ next = coords[i+2]
+
+ previous = coords[i]
+
+ if (closed) :
+ pts.extend((pts[0], pts[1], pts[2], pts[3]))
+
+ return pts
+
+
+def curveline_coords(coords, **options) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::curveline_coords
+ # retourne les coordonnées d'une curveLine
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste de coordonnées des points de la ligne
+ # options :
+ # -closed : <boolean> ligne fermée
+ # -shifting : <out|center|in> sens de décalage du contour
+ # (par défaut center)
+ # -linewidth : <dimension> epaisseur de la ligne
+ #---------------------------------------------------------------------------
+ """
+ numfaces = len(coords)
+ gopts = []
+ backpts = []
+ pts = []
+
+ if options.has_key('closed'):
+ closed = options['closed']
+ else:
+ closed = None
+ if (options.has_key('linewidth')) :
+ linewidth = options['linewidth']
+ else:
+ linewidth = 2
+ if (options.has_key('shifting')) :
+ shifting = options['shifting']
+ else:
+ shifting = 'center'
+
+ if( not numfaces or linewidth < 2):
+ raise ValueError("Bad coords %s or linewidth %s"%(numfaces, linewidth))
+
+ if (closed) :
+ previous = coords[numfaces - 1]
+ else:
+ previous = None
+
+ next = coords[1]
+ if (shifting == 'center'):
+ linewidth /= 2
+
+ for i in xrange(0, numfaces):
+ pt = coords[i]
+
+ if ( previous is None ) :
+ # extrémité de curve sans raccord -> angle plat
+ previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
+
+
+ (angle, bisecangle) = vertex_angle(previous, pt, next)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+ if (asin) :
+ delta = abs(linewidth / asin)
+ else:
+ delta = linewidth
+
+ if (shifting == 'out' or shifting == 'in') :
+ if (shifting == 'out') :
+ adding = -90
+ else:
+ adding = 90
+ pts.append(rad_point(pt, delta, bisecangle + adding))
+ pts.append(pt)
+
+ else :
+ pts = rad_point(pt, delta, bisecangle+90)
+ gopts.append(pts)
+ pts = rad_point(pt, delta, bisecangle-90)
+ backpts.insert(0, pts)
+
+ if (i == numfaces - 2) :
+ if (closed) :
+ next = coords[0]
+ else:
+ next = (coords[i+1][0] +
+ (coords[i+1][0] - pt[0]), coords[i+1][1]
+ + (coords[i+1][1] - pt[1]))
+ else :
+ next = coords[i+2]
+
+ previous = coords[i]
+
+ gopts.extend(backpts)
+
+ if (closed) :
+ gopts.extend ((gopts[0], gopts[1]))
+
+ return gopts
+
+
+def shiftpath_coords(coords, **options) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::shiftpath_coords
+ # retourne les coordonnées d'un décalage de path
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordsList> liste de coordonnées des points du path
+ # options :
+ # -closed : <boolean> ligne fermée
+ # -shifting : <'out'|'in'> sens de décalage du path (par défaut out)
+ # -width : <dimension> largeur de décalage (par défaut 1)
+ #---------------------------------------------------------------------------
+ """
+ numfaces = len(coords)
+
+ if options.has_key('closed'):
+ closed = options['closed']
+ else:
+ closed = None
+ if (options.has_key('width')) :
+ width = options['width']
+ else:
+ width = 1
+ if (options.has_key('shifting')) :
+ shifting = options['shifting']
+ else:
+ shifting = 'out'
+
+ if (not numfaces or not width):
+ return coords
+
+ pts = []
+
+ if (closed) :
+ previous = coords[numfaces - 1]
+ else:
+ previous = None
+ next = coords[1]
+
+ for i in xrange(0, numfaces):
+ pt = coords[i]
+
+ if ( previous is None ) :
+ # extrémité de curve sans raccord -> angle plat
+ previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
+
+
+ (angle, bisecangle) = vertex_angle(previous, pt, next)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+ if (asin) :
+ delta = abs(width / asin)
+ else:
+ delta = width
+
+ if (shifting == 'out') :
+ adding = -90
+ else:
+ adding = 90
+ (x, y) = rad_point(pt, delta, bisecangle + adding)
+ pts.append((x, y))
+
+
+ if (i > numfaces - 3) :
+ if (closed) :
+ next = coords[0]
+ else:
+ next = (pt[0] + (pt[0] - previous[0]),
+ pt[1] + (pt[1] - previous[1]))
+
+ else :
+ next = coords[i+2]
+
+ previous = coords[i]
+
+ return pts
+
+
+
+
+def curveitem2polyline_coords(widget, item, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::curveitem2polyline_coords
+ # Conversion des coordonnées Znitem curve (multicontours)
+ # en coordonnées polyline(s)
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # item : <tagOrId> identifiant de l'item source
+ # options :
+ # -tunits : <integer> nombre pas de division des segments bezier
+ # (par défaut 20)
+ # -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
+ #---------------------------------------------------------------------------
+ """
+ if (not widget.type(item)):
+ raise ValueError("Item Not Found")
+ coords = []
+ numcontours = widget.contour(item)
+ #parentgroup = widget.group(item)
+
+ for contour in xrange(0, numcontours):
+ points = widget.coords(item, contour)
+ contourcoords = curve2polyline_coords(points, **options)
+
+ coords.append(contourcoords)
+
+ return coords
+
+def curve2polyline_coords(points, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::curve2polyline_coords
+ # Conversion curve -> polygone
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # points : <coordsList> liste des coordonnées curve à transformer
+ # options :
+ # -tunits : <integer> nombre pas de division des segments bezier
+ # (par défaut 20)
+ # -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('tunits')) :
+ tunits = options['tunits']
+ else:
+ tunits = 20
+ if (options.has_key('adjust')) :
+ adjust = options['adjust']
+ else:
+ adjust = 1
+
+ poly = []
+ previous = None
+ bseg = []
+ numseg = 0
+ #prevtype = None
+
+ for point in points:
+ if len(point) == 3:
+ (x, y, c) = point
+ elif len(point) == 2:
+ (x, y, c) = (point, None)
+ else:
+ ValueError("Bad point")
+ if (c == 'c') :
+ if not len(bseg) and previous:
+ bseg.append(previous)
+ bseg.append(point)
+
+ else :
+ if (len (bseg)) :
+ bseg.append(point)
+ if (adjust) :
+ pts = bezier_compute(bseg, skipend = 1)
+ del pts[0]
+ del pts[0]
+ poly.extend(pts)
+
+ else :
+ pts = bezier_segment(bseg, tunits = tunits, skipend = 1)
+ del pts[0]
+ del pts[0]
+ poly.extend(pts)
+
+ bseg = []
+ numseg += 1
+ #prevtype = 'bseg'
+
+ else :
+ poly.append((x, y))
+ #prevtype = 'line'
+
+ previous = point
+
+
+ return poly
+
+
+def build_tabboxitem(widget, parentgroup, **options):
+ """
+ #-------------------------------------------------------------------------------
+ # Graphics::build_tabboxitem
+ # construit les items de représentations Zinc d'une boite à onglets
+ #-------------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # parentgroup : <tagOrId> identifiant de l'item group parent
+ #
+ # options :
+ # -coords : <coordsList> coordonnées haut-gauche et bas-droite
+ # du rectangle
+ # englobant du Tabbox
+ # -params : <hastable> arguments spécifiques des items curve
+ # à passer au widget
+ # -texture : <imagefile> ajout d'une texture aux items curve
+ # -tabtitles : <hashtable> table de hash de définition des titres onglets
+ # -pageitems : <hashtable> table de hash de définition des pages internes
+ # -relief : <hashtable> table de hash de définition du relief de forme
+ #
+ # (options de construction géometrique passées à tabbox_coords)
+ # -numpages : <integer> nombre de pages (onglets) de la boite
+ # -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la ligne
+ # d'onglets
+ # -alignment : <'left'|'center'|'right'> alignement des onglets sur le coté
+ # d'ancrage
+ # -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
+ # 'auto' largeur répartie, les largeurs sont auto-ajustée
+ # si besoin.
+ # -tabheight : <'auto'>|<dimension> : hauteur des onglets
+ # -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut de
+ # l'onglet (défaut auto)
+ # -radius : <dimension> rayon des arrondis d'angle
+ # -overlap : <'auto'>|<dimension> offset de recouvrement/séparation entre
+ # onglets
+ # -corners : <booleanList> liste 'spécifique' des raccords de sommets [0|1]
+ #---------------------------------------------------------------------------
+ """
+ if options.has_key('coords') :
+ coords = options['coords']
+ else:
+ raise ValueError("Coords needed")
+ if options.has_key('params'):
+ params = options['params']
+ else:
+ params = {}
+ if params.has_key('tags'):
+ tags = params['tags']
+ else :
+ tags = []
+ texture = None
+
+ if (options.has_key('texture')) :
+ texture = get_texture(widget,
+ options['texture'])
+
+
+ if options.has_key('tabtitles'):
+ titlestyle = options['tabtitles']
+ else :
+ titlestyle = None
+ if (titlestyle) :
+ titles = titlestyle['text']
+ else:
+ titles = None
+
+ tabs = []
+ (shapes, tcoords, invert) = tabbox_coords(**options)
+ if (invert) :
+ k = len(shapes)
+ else:
+ k = -1
+ shapes.reverse()
+ for shape in shapes :
+ if (invert) :
+ k -= 1
+ else :
+ k += +1
+ group = widget.add('group', parentgroup)
+ params['tags'] = tags
+ params['tags'] += (k, 'intercalaire')
+ form = widget.add('curve',
+ group,
+ lpts2coords(shape),
+ **params)
+ if texture :
+ widget.itemconfigure(form, tile = texture)
+
+ if (options.has_key('relief')) :
+ graphicitem_relief(widget, form, **options['relief'])
+
+
+ if (options.has_key('page')) :
+ build_zinc_item(widget, group, **options['page'])
+
+ if (titles) :
+ if (invert) :
+ tindex = k
+ else:
+ tindex = len(shapes) - k
+ titlestyle['itemtype'] = 'text'
+ titlestyle['coords'] = tcoords[tindex]
+ titlestyle['params']['text'] = titles[tindex]
+ ltags = list(tags)
+ ltags.append(tindex)
+ ltags.append('titre')
+ titlestyle['params']['tags'] = tuple(ltags)
+ build_zinc_item(widget, group, **titlestyle)
+
+ return tabs
+
+
+def tabbox_coords(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # tabbox_coords
+ # Calcul des shapes de boites à onglets
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : <coordList> coordonnées haut-gauche bas-droite du rectangle
+ # englobant de la tabbox
+ # options
+ # -numpages : <integer> nombre de pages (onglets) de la boite
+ # -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la
+ # ligne d'onglets
+ # -alignment : <'left'|'center'|'right'> alignement des onglets
+ # sur le coté d'ancrage
+ # -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
+ # 'auto' largeur répartie, les largeurs sont auto-ajustée
+ # si besoin.
+ # -tabheight : <'auto'>|<dimension> : hauteur des onglets
+ # -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut
+ # de l'onglet (défaut auto)
+ # -radius : <dimension> rayon des arrondis d'angle
+ # -overlap : <'auto'>|<dimension> offset de recouvrement/séparation
+ # entre onglets
+ # -corners : <booleanList> liste 'spécifique' des raccords
+ # de sommets [0|1]
+ #---------------------------------------------------------------------------
+ """
+ (x_0, y_0) = coords[0]
+ (x_n, y_n) = coords[1]
+ shapes, titles_coords = [], []
+ inverse = None
+
+ #loptions = options.keys()
+ if options.has_key('numpages'):
+ numpages = options['numpages']
+ else:
+ numpages = 0
+
+ if (not x_0 or not y_0 or not x_n or not y_n or not numpages) :
+ raise ValueError("Vous devez au minimum spécifier\
+ le rectangle englobant et le nombre de pages")
+
+ if (options.has_key('anchor')) :
+ anchor = options['anchor']
+ else:
+ anchor = 'n'
+ if (options.has_key('alignment')) :
+ alignment = options['alignment']
+ else:
+ alignment ='left'
+
+
+ if (options.has_key('tabwidth')) :
+ nlen = options['tabwidth']
+ else:
+ nlen ='auto'
+ if (options.has_key('tabheight')) :
+ thick = options['tabheight']
+ else:
+ thick ='auto'
+ if (options.has_key('tabshift')) :
+ biso = options['tabshift']
+ else:
+ biso = 'auto'
+ if (options.has_key('radius')) :
+ radius = options['radius']
+ else:
+ radius = 0
+ if (options.has_key('overlap')) :
+ overlap = options['overlap']
+ else:
+ overlap = 0
+ if (options.has_key('corners')):
+ corners = options['corners']
+ else:
+ corners = None
+ if (anchor in ( 'n', 's')) :
+ orientation = 'horizontal'
+ else:
+ orientation = 'vertical'
+ if (orientation == 'horizontal') :
+ maxwidth = (x_n - x_0)
+ else:
+ maxwidth = (y_n - y_0)
+ tabswidth = 0
+ align = 1
+
+ if (nlen == 'auto') :
+ tabswidth = maxwidth
+ nlen = float(tabswidth + (overlap * (numpages - 1)))/numpages
+ else :
+ if (type(nlen) in (types.TupleType, types.ListType )) :
+ for w in nlen :
+ tabswidth += (w - overlap)
+
+ tabswidth += overlap
+ else :
+ tabswidth = (nlen * numpages) - (overlap * (numpages - 1))
+
+
+ if (tabswidth > maxwidth) :
+ tabswidth = maxwidth
+ nlen = float(tabswidth + (overlap * (numpages - 1)))/numpages
+
+ if (alignment == 'center' and ((maxwidth - tabswidth) > radius)):
+ align = 0
+
+
+ if (thick == 'auto') :
+ if (orientation == 'horizontal') :
+ thick = int((y_n - y_0)/10)
+ else:
+ thick = int((x_n - y_0)/10)
+ thick = max(10, thick)
+ thick = min(40, thick)
+
+ if (biso == 'auto') :
+ biso = int(thick/2)
+
+ if ((alignment == 'right' and anchor != 'w') or
+ (anchor == 'w' and alignment != 'right')) :
+
+ if (type(nlen) in (types.TupleType, types.ListType)) :
+ for p in xrange(0, numpages):
+ nlen[p] *= -1
+ else :
+ nlen *= -1
+ biso *= -1
+ overlap *= -1
+
+ if (alignment == 'center') :
+ (biso1, biso2) = (biso/2, biso/2)
+ else:
+ (biso1, biso2) = (0, biso)
+
+ cadre, tabdxy = [], []
+ xref, yref = 0, 0
+ if (orientation == 'vertical') :
+ if (anchor == 'w'):
+ thick *= -1
+ if (anchor == 'w') :
+ (startx, endx) = (x_0, x_n)
+ else:
+ (startx, endx) = (x_n, x_0)
+ if ((anchor == 'w' and alignment != 'right') or
+ (anchor == 'e' and alignment == 'right')) :
+ (starty, endy) = (y_n, y_0)
+ else:
+ (starty, endy) = (y_0, y_n)
+
+ xref = startx - thick
+ yref = starty
+ if (alignment == 'center') :
+ if (anchor == 'w') :
+ ratio = -2
+ else:
+ ratio = 2
+ yref += (float(maxwidth - tabswidth)/ratio)
+
+ cadre = ((xref, endy), (endx, endy), (endx, starty), (xref, starty))
+
+ # flag de retournement de la liste des pts de curve si nécessaire
+ # -> sens anti-horaire
+ inverse = (alignment == 'right')
+
+ else :
+ if (anchor == 's'):
+ thick *= -1
+ (starty, endy) = (y_n, y_0)
+ else :
+ (starty, endy) = (y_0, y_n)
+
+ if (alignment == 'right') :
+ (startx, endx) = (x_n, x_0)
+ else:
+ (startx, endx) = (x_0, x_n)
+
+
+ yref = starty + thick
+ if (alignment == 'center') :
+ xref = x_0 + (float(maxwidth - tabswidth)/2)
+ else :
+ xref = startx
+
+ cadre = ((endx, yref), (endx, endy), (startx, endy), (startx, yref))
+
+ # flag de retournement de la liste des pts de curve si nécessaire
+ # -> sens anti-horaire
+ inverse = ((anchor == 'n' and alignment != 'right')
+ or (anchor == 's' and alignment == 'right'))
+
+
+ for i in xrange(0, numpages):
+ pts = []
+
+ # décrochage onglet
+ #push (pts, ([xref, yref])) if i > 0
+
+ # cadre
+ pts.extend(cadre)
+
+ # points onglets
+ if (i > 0 or not align) :
+ pts.append((xref, yref))
+
+ if (type(nlen) in (types.TupleType, types.ListType)) :
+ tw = nlen[i]
+ else:
+ tw = nlen
+
+ if (type(nlen) in (types.TupleType, types.ListType)) :
+ slen = len(nlen)
+ else:
+ slen = nlen
+
+ if (orientation == 'vertical') :
+ tabdxy = ((thick, biso1), (thick, tw - biso2), (0, tw))
+ else:
+ tabdxy = ((biso1, -thick), (tw - biso2, -thick), (tw, 0))
+ for delta_xy in tabdxy :
+ pts.append((xref + delta_xy[0], yref + delta_xy[1]))
+
+
+ if (radius) :
+ if (not options.has_key('corners')) :
+ if (i > 0 or not align) :
+ corners = (0, 1, 1, 0, 0, 1, 1, 0)
+ else :
+ corners = (0, 1, 1, 0, 1, 1, 0, 0, 0)
+
+ curvepts = roundedcurve_coords(pts,
+ radius = radius,
+ corners = corners)
+ lcurvepts = list(curvepts)
+ if (inverse):
+ lcurvepts.reverse()
+ shapes.append(lcurvepts)
+ else :
+ if (inverse):
+ pts.reverse()
+ shapes.append(pts)
+
+ if (orientation == 'horizontal') :
+ titles_coords.append((float(xref) + (tw - (biso2 - biso1))/2,
+ float(yref) - (thick/2)))
+ xref += (tw - overlap)
+
+ else :
+ titles_coords.append( (float(xref) + (thick/2),
+ yref + (slen - ((biso2 - biso1)/2))/2))
+ yref += (slen - overlap)
+
+ return (shapes, titles_coords, inverse)
+
+
+def graphicitem_relief(widget, item, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::graphicitem_relief
+ # construit un relief à l'item Zinc en utilisant des items Triangles
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # item : <tagOrId> identifiant de l'item zinc
+ # options : <hash> table d'options
+ # -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
+ # -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
+ # -relief : <'raised'|'sunken'> (défaut 'raised')
+ # -side : <'inside'|'outside'> relief interne ou externe à la forme
+ # (défaut 'inside')
+ # -color : <color> couleur du relief (défaut couleur de la forme)
+ # -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
+ # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
+ # -width : <dimension> 'épaisseur' du relief en pixel
+ # -fine : <boolean> mode précision courbe de bezier
+ # (défaut 0 : auto-ajustée)
+ #-------------------------------------------------------------------------------
+ """
+ items = []
+
+ # relief d'une liste d'items -> appel récursif
+ if (type(item) in (types.TupleType, types.ListType)) :
+ for part in item :
+ items.extend(graphicitem_relief(widget, part, **options))
+ else :
+ itemtype = widget.type(item)
+ if not itemtype:
+ raise ValueError("Bad Item")
+
+ parentgroup = widget.group(item)
+ if (options.has_key('priority')) :
+ priority = options['priority']
+ else :
+ priority = widget.itemcget(item, 'priority')+1
+
+ # coords transformés (polyline) de l'item
+ adjust = not options['fine']
+ for coords in zincitem_2_curvecoords(widget,
+ item, linear = 1,
+ realcoords = 1,
+ adjust = adjust) :
+ (pts, colors) = polyline_relief_params(widget,
+ item,
+ coords,
+ **options)
+
+ items.append(widget.add('triangles',
+ parentgroup,
+ pts,
+ priority = priority,
+ colors = colors))
+
+
+ # renforcement du contour
+ if (widget.itemcget(item, 'linewidth')) :
+ items.append(widget.clone(item,
+ filled = 0,
+ priority = priority+1))
+
+ return items
+
+
+def polyline_relief_params(widget, item, coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::polyline_relief_params
+ # retourne la liste des points et des couleurs nécessaires à la construction
+ # de l'item Triangles du relief
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant widget Zinc
+ # item : <tagOrId> identifiant item Zinc
+ # options : <hash> table d'options
+ # -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
+ # -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
+ # -relief : <'raised'|'sunken'> (défaut 'raised')
+ # -side : <'inside'|'outside'> relief interne ou externe à la forme
+ # (défaut 'inside')
+ # -color : <color> couleur du relief (défaut couleur de la forme)
+ # -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
+ # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
+ # -width : <dimension> 'épaisseur' du relief en pixel
+ #---------------------------------------------------------------------------
+ """
+
+ if (options.has_key('closed')) :
+ closed = options['closed']
+ else:
+ closed = 1
+ if (options.has_key('profil')) :
+ profil = options['profil']
+ else:
+ profil = 'rounded'
+ if (options.has_key('relief')) :
+ relief = options['relief']
+ else :
+ relief = 'raised'
+ if (options.has_key('side')) :
+ side = options['side']
+ else:
+ side = 'inside'
+ if (options.has_key('color')) :
+ basiccolor = options['color']
+ else:
+ basiccolor = zincitem_predominantcolor(widget, item)
+ if (options.has_key('smooth')) :
+ smoothed = options['smooth']
+ else:
+ smoothed = 1
+ if (options.has_key('lightangle')) :
+ lightangle = options['lightangle']
+ else:
+ lightangle = widget.cget('lightangle')
+
+ if options.has_key('width'):
+ width = options['width']
+ else:
+ raise ValueError('Options must have width field')
+ if ( width < 1) :
+ (x_0, y_0, x_1, y_1) = widget.bbox(item)
+ width = min(x_1 -x_0, y_1 - y_0)/10
+ if (width < 2) :
+ width = 2
+
+ numfaces = len(coords)
+ if (closed):
+ previous = coords[numfaces - 1]
+ else:
+ previous = None
+ next = coords[1]
+
+ pts = []
+ colors = []
+ alpha = 100
+ m = re.compile("^(?P<color>#[0-9a-fA-F]{6});(?P<alpha>\d{1,2})$")
+ res = m.match(basiccolor)
+ if (res is not None) :
+ (basiccolor, alpha) = res.group('color'), res.group('alpha')
+
+ if ( options.has_key('color')):
+ color = options['color']
+ res = m.match(color)
+ if ((res is None) and (profil == 'flat')):
+ alpha /= 2
+
+ if (profil == 'rounded') :
+ reliefalphas = [0, alpha]
+ else:
+ reliefalphas = [alpha, alpha]
+
+ for i in xrange(0, numfaces):
+ pt = coords[i]
+
+ if (previous) :
+ # extrémité de curve sans raccord -> angle plat
+ previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
+
+
+ (angle, bisecangle) = vertex_angle(previous, pt, next)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+ if (asin) :
+ delta = abs(width / asin)
+ else:
+ delta = width
+ if (side == 'outside') :
+ decal = -90
+ else:
+ decal = 90
+
+ shift_pt = rad_point(pt, delta, bisecangle+decal)
+ pts.append(shift_pt)
+ pts.append(pt)
+
+ if (smoothed and i) :
+ pts.append(shift_pt)
+ pts.append(pt)
+
+
+ faceangle = 360 -(linenormal(previous, next)+90)
+
+ light = abs(lightangle - faceangle)
+ if (light > 180):
+ light = 360 - light
+ if light < 1:
+ light = 1
+
+ if (relief == 'sunken') :
+ lumratio = (180-light)/180
+ else:
+ lumratio = light/180
+
+ if ( not smoothed and i) :
+ #A VOIR
+ #OBSCURE
+ colors.extend((colors[-2], colors[-1]))
+
+ if (basiccolor) :
+ # création des couleurs dérivées
+ shade = lightingcolor(basiccolor, lumratio)
+ color0 = "%s;%s"% (shade, reliefalphas[0])
+ color1 = "%s;%s"% (shade, reliefalphas[1])
+ colors.extend((color0, color1))
+
+ else :
+ c = (255*lumratio)
+ color0 = hexargbcolor(c, c, c, reliefalphas[0])
+ color1 = hexargbcolor(c, c, c, reliefalphas[1])
+ colors.extend((color0, color1))
+
+
+ if (i == (numfaces - 2)) :
+ if (closed) :
+ next = coords[0]
+ else:
+ next = (coords[i+1][0] + (coords[i+1][0] - pt[0]),
+ coords[i+1][1] + (coords[i+1][1] - pt[1]))
+ else :
+ next = coords[i+2]
+
+ previous = coords[i]
+
+ if (closed) :
+ pts.extend((pts[0], pts[1], pts[2], pts[3]))
+ colors.extend((colors[0], colors[1]))
+
+ if (not smoothed) :
+ pts.extend((pts[0], pts[1], pts[2], pts[3]))
+ colors.extend((colors[0], colors[1]))
+
+ return (pts, colors)
+
+
+def graphicitem_shadow(widget, item, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::graphicitem_shadow
+ # Création d'une ombre portée à l'item
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant widget Zinc
+ # item : <tagOrId> identifiant item Zinc
+ # options : <hash> table d'options
+ # -opacity : <percent> opacité de l'ombre (défaut 50)
+ # -filled : <boolean> remplissage totale de l'ombre (hors bordure) (defaut 1)
+ # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
+ # -distance : <dimension> distance de projection de l'ombre en pixel
+ # -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 0)
+ # -width : <dimension> taille de diffusion/diffraction (défaut 4)
+ # -color : <color> couleur de l'ombre portée (défaut black)
+ #---------------------------------------------------------------------------
+ """
+ items = []
+
+ # relief d'une liste d'items -> appel récursif
+ if (type(item) in (types.TupleType, types.ListType)) :
+ for part in item :
+ items.append(graphicitem_shadow(widget, part, **options))
+ return items
+
+ else :
+
+ itemtype = widget.type(item)
+
+ if not itemtype :
+ raise ValueError("Not a valid Item Id %s"%item)
+
+ # création d'un groupe à l'ombre portée
+ if (options.has_key('parentgroup')) :
+ parentgroup = options['parentgroup']
+ else:
+ parentgroup = widget.group(item)
+ if (options.has_key('priority')) :
+ priority = options['priority']
+ else:
+ priority = widget.itemcget(item, 'priority')-1
+ priority = max(0, priority)
+
+ shadow = widget.add('group', parentgroup, priority = priority)
+
+ if (itemtype == 'text') :
+ if (options.has_key('opacity')) :
+ opacity = options['opacity']
+ else:
+ opacity = 50
+ if (options['color']) :
+ color = options['color']
+ else:
+ color = '#000000'
+
+ clone = widget.clone(item, color = "%s;%s"% (color, opacity))
+ widget.chggroup(clone, shadow)
+
+ else :
+
+ # création des items (de dessin) de l'ombre
+ if ( options.has_key('filled')) :
+ filled = options['filled']
+ else:
+ filled = 1
+
+ # coords transformés (polyline) de l'item
+ for coords in zincitem_2_curvecoords(widget,
+ item,
+ linear = 1,
+ realcoords = 1) :
+ (t_pts, i_pts, colors) = polyline_shadow_params( coords,
+ **options)
+
+ # option filled : remplissage hors bordure
+ # de l'ombre portée (item curve)
+ if (filled) :
+ if (len(items)) :
+ widget.contour(items[0], 'add', 0, i_pts)
+
+ else :
+ items.append( widget.add('curve', shadow, i_pts,
+ linewidth = 0,
+ filled = 1,
+ fillcolor = colors[0],
+ ))
+
+ # bordure de diffusion de l'ombre (item triangles)
+ items.append( widget.add('triangles', shadow, t_pts,
+ colors = colors))
+
+
+ # positionnement de l'ombre portée
+ if (options.has_key('distance')) :
+ distance = options['distance']
+ else:
+ distance = 10
+ if (options.has_key('lightangle')) :
+ lightangle = options['lightangle']
+ else:
+ lightangle = widget.cget('lightangle')
+
+ (delta_x, delta_y) = rad_point((0, 0),
+ distance,
+ lightangle+180)
+ widget.translate(shadow, delta_x, -delta_y)
+
+ return shadow
+
+
+def polyline_shadow_params(coords, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::polyline_shadow_params
+ # retourne les listes des points et de couleurs nécessaires à la
+ # construction des items triangles (bordure externe) et curve
+ # (remplissage interne) de l'ombre portée
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # coords : coordonnées
+ # options : <hash> table d'options
+ # -opacity : <percent> opacité de l'ombre (défaut 50)
+ # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
+ # -distance : <dimension> distance de projection de l'ombre en pixel
+ # (défaut 10)
+ # -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 2)
+ # -width : <dimension> taille de diffusion/diffraction
+ # (défaut distance -2)
+ # -color : <color> couleur de l'ombre portée (défaut black)
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('distance')) :
+ distance = options['distance']
+ else:
+ distance = 10
+ if (options.has_key('width')) :
+ width = options['width']
+ else:
+ width = distance-2
+ if (options.has_key('opacity')) :
+ opacity = options['opacity']
+ else:
+ opacity = 50
+ if (options.has_key('color')) :
+ color = options['color']
+ else:
+ color ='#000000'
+ if (options.has_key('enlarging')) :
+ enlarging = options['enlarging']
+ else :
+ enlarging = 2
+
+ if (enlarging) :
+ coords = shiftpath_coords(coords,
+ width = enlarging,
+ closed = 1,
+ shifting = 'out')
+
+ numfaces = len(coords)
+ previous = coords[numfaces - 1]
+ next = coords[1]
+
+ t_pts = []
+ i_pts = []
+ colors = []
+ (color0, color1) = ("%s;%s"% (color, opacity), "%s;0"% color)
+
+ for i in xrange(0, numfaces):
+ pt = coords[i]
+
+ #A VOIR
+ #Je ne vois pas quand cela peut arriver
+ if (not previous) :
+ # extrémité de curve sans raccord -> angle plat
+ previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
+
+ (angle, bisecangle) = vertex_angle(previous, pt, next)
+
+ # distance au centre du cercle inscrit : rayon/sinus demi-angle
+ asin = sin(radians(angle/2))
+ if (asin) :
+ delta = abs(width / asin)
+ else :
+ delta = width
+ decal = 90
+
+ shift_pt = rad_point(pt, delta, bisecangle+decal)
+ i_pts.append(shift_pt)
+ t_pts.append(shift_pt)
+ t_pts.append(pt)
+
+ colors.append(color0)
+ colors.append(color1)
+ if (i == numfaces - 2) :
+ next = coords[0]
+ else :
+ next = coords[i+2]
+
+ previous = coords[i]
+
+ # fermeture
+ t_pts.extend((t_pts[0], t_pts[1], t_pts[2], t_pts[3]))
+ i_pts.extend((t_pts[0], t_pts[1]))
+ colors.extend((color0, color1, color0, color1))
+
+ return (t_pts, i_pts, colors)
+
+
+
+
+
+#Local Variables:
+#mode : python
+#tab-width: 4
+#end:
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/pictorial.py b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/pictorial.py
new file mode 100755
index 0000000..1599935
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/Zinc/pictorial.py
@@ -0,0 +1,766 @@
+# -*- coding: iso-8859-1 -*-
+# Pictorial Functions :
+# ----------------------
+# set_gradients
+# get_pattern
+# get_texture
+# get_image
+# init_pixmaps
+# zincitem_predominantcolor
+# zncolor_to_rgb
+# hexargbcolor
+# create_graduate
+# path_graduate
+# mediancolor
+# lightingcolor
+# rgb_to_lch
+# lch_to_rgb
+# rgb_to_hls
+# hls_to_rgb
+
+import PIL.Image, PIL.ImageTk
+import re
+from math import pi, radians, atan2, sqrt, sin, cos
+
+# initialisation et partage de ressources couleurs et images
+textures = {}
+IMAGES = {}
+bitmaps = {}
+AVERAGE_COLOR = '#777777'
+
+
+_GRADIENTS = []
+
+# constante white point (conversion couleur espace CIE XYZ)
+(Xw, Yw, Zw) = (95.047, 100.0, 108.883)
+
+def set_gradients(zinc, **grads):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::set_gradients
+ # création de gradient nommés Zinc
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # **grads : <dictionnaire> de définition de couleurs zinc
+ #---------------------------------------------------------------------------
+ """
+ global _GRADIENTS
+ if (not _GRADIENTS):
+ _GRADIENTS = []
+ for (name, gradient) in grads.items():
+ zinc.gname(gradient, name)
+ _GRADIENTS.append(name)
+
+def rgb_dec2hex(rgb):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rgb_dec2hex
+ # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # rgb : <rgbColorList> liste de couleurs au format RGB
+ #---------------------------------------------------------------------------
+ """
+ return "#%04x%04x%04x"% rgb
+
+def path_graduate(zinc, numcolors, style):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::path_graduate
+ # création d'un jeu de couleurs dégradées pour item pathline
+ #---------------------------------------------------------------------------
+ """
+ typ = style['type']
+ if (typ == 'linear'):
+ return create_graduate(numcolors, style['colors'], 2)
+ elif (typ == 'double'):
+ colors1 = create_graduate(numcolors/2+1,
+ style['colors'][0])
+ colors2 = create_graduate(numcolors/2+1,
+ style['colors'][1])
+ colors = []
+ for i in xrange(numcolors+1):
+ colors.extend([colors1[i], colors2[i]])
+ return colors
+ elif (typ == 'transversal'):
+ (c1, c2) = style['colors']
+ colors = [c1, c2]
+ for i in xrange(numcolors):
+ colors.extend([c1, c2])
+
+ return colors
+
+def create_graduate(totalsteps, refcolors, repeat = 1):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::create_graduate
+ # création d'un jeu de couleurs intermédiaires (dégradé) entre n couleurs
+ #---------------------------------------------------------------------------
+ """
+ colors = []
+
+ numgraduates = len(refcolors) - 1
+ if (numgraduates < 1):
+ raise ValueError("Le degradé necessite\
+ au moins 2 couleurs de référence...")
+ steps = None
+ if (numgraduates > 1):
+ steps = totalsteps/(numgraduates - 1)
+ else:
+ steps = totalsteps
+
+ for c in xrange(numgraduates):
+ (c1, c2) = (refcolors[c], refcolors[c + 1])
+
+ for i in xrange(steps):
+ color = mediancolor(c1, c2, i / (steps - 1))
+ for it in xrange(repeat):
+ colors.append(color)
+
+ if (c < numgraduates - 1):
+ for k in xrange(repeat):
+ colors.pop()
+
+ return colors
+
+def lightingcolor (color, new_l) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::lightingcolor
+ # modification d'une couleur par sa composante luminosité
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # color : <color> couleur au format zinc
+ # new_l : <pourcent> (de 0 à 1) nouvelle valeur de luminosité
+ #---------------------------------------------------------------------------
+ """
+ (h, l, s) = 0, 0, 0
+ rgb = hexa2rgb(color)
+ h, l, s = rgb_to_hls(rgb)
+ new_l = min(new_l, 1)
+ (n_r, n_g, n_b) = hls_to_rgb(h, new_l, s)
+ return hexargbcolor(n_r*255, n_g*255, n_b*255)
+
+
+def get_predominantcolor(colors):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::get_predominantcolor
+ # donne la couleur dominante
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # colors : <color>* liste de couleurs au format zinc
+ #---------------------------------------------------------------------------
+ """
+ (rs, gs, bs, as_, numcolors) = (0, 0, 0, 0, 0)
+ for color in colors :
+ (r, g, b, a) = zncolor_to_rgb(color)
+ rs += r
+ gs += g
+ bs += b
+ as_ += a
+ numcolors += 1
+
+ new_r = int(rs/numcolors)
+ new_g = int(gs/numcolors)
+ new_b = int(bs/numcolors)
+ new_a = int(as_/numcolors)
+
+ newcolor = hexargbcolor(new_r, new_g, new_b, new_a)
+ return newcolor
+
+def zincitem_predominantcolor(widget, item):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::zincitem_predominantcolor
+ # retourne la couleur dominante d'un item ('barycentre' gradiant fillcolor)
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # item : <tagOrId> identifiant de l'item zinc
+ #---------------------------------------------------------------------------
+ """
+ typ = widget.type(item)
+ if not typ :
+ raise ValueError("Not a Valid Item %s" % item)
+ if (typ == 'text' or typ == 'icon') :
+ return widget.itemcget(item, 'color')
+
+ elif (typ == 'triangles' or
+ typ == 'rectangle' or
+ typ == 'arc' or
+ typ == 'curve') :
+
+ colors = []
+
+ if (typ == 'triangles') :
+ colors = widget.itemcget(item, 'colors')
+ else :
+ grad = widget.itemcget(item, 'fillcolor')
+ regexp = re.compile(
+ "^=(?P<class>\w+)(?P<params>[^|]+)\|(?P<colorparts>.*)$")
+ res = regexp.match(grad)
+ if (res is None):
+ #couleur simple
+ return grad
+ else:
+ #Gradient
+ colorspart = res.group('colorparts').split("|")
+ regexp_color = re.compile("^(?P<color>^\S+).*")
+ for colorpart in colorspart:
+ res = regexp_color.match(colorpart)
+ if res:
+ colors.append(res.group('color'))
+ else :
+ raise ValueError("Impossible case!!")
+ return get_predominantcolor(colors)
+ else :
+ return AVERAGE_COLOR
+
+def mediancolor (color1, color2, rate) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::mediancolor
+ # calcul d'une couleur intermédiaire défini par un ratio ($rate)
+ # entre 2 couleurs
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # color1 : <color> première couleur zinc
+ # color2 : <color> seconde couleur zinc
+ # rate : <pourcent> (de 0 à 1) position de la couleur intermédiaire
+ #---------------------------------------------------------------------------
+ """
+ if (rate > 1):
+ rate = 1
+ if (rate < 0):
+ rate = 0
+
+ (r0, g0, b0, a0) = zncolor_to_rgb(color1)
+ (r1, g1, b1, a1) = zncolor_to_rgb(color2)
+
+ r = r0 + int((r1 - r0) * rate)
+ g = g0 + int((g1 - g0) * rate)
+ b = b0 + int((b1 - b0) * rate)
+ a = a0 + int((a1 - a0) * rate)
+
+ return hexargbcolor(r, g, b, a)
+
+
+def zncolor_to_rgb (zncolor):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::zncolor_to_rgb
+ # conversion d'une couleur Zinc au format RGBA (255,255,255,100)
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # zncolor : <color> couleur au format hexa zinc (#ffffff ou #ffffffffffff)
+ #---------------------------------------------------------------------------
+ """
+ #Recherche du format d'entrée
+ # ffffff ou ffffffffffff avec ou sans alpha
+ #test présence alpha
+ res = []
+ res.append(
+ re.match(
+ "^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2});(?P<alpha>\d{1,3})$"
+ ,zncolor))
+ res.append(
+ re.match(
+ "^#([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4});(?P<alpha>\d{1,3})$"
+ ,zncolor))
+ #Pas de alpha
+ res.append(re.match("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$"
+ ,zncolor))
+ res.append(re.match("^#([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})$"
+ ,zncolor))
+ res.sort()
+ resultat = res.pop()
+ if res is None:
+ raise ValueError("Not a valid zinc color")
+ alpha = 100
+ res = resultat.groupdict()
+ if res.has_key('alpha'):
+ alpha = int(res['alpha'])
+ else:
+ alpha = 100
+
+ R = int(resultat.group(1), 16)
+ G = int(resultat.group(2), 16)
+ B = int(resultat.group(3), 16)
+
+ return (R, G, B, alpha)
+
+def rgb_to_lch(r, g, b) :
+ """
+ #---------------------------------------------------------------------------
+ # ALGORYTHMES DE CONVERSION ENTRE ESPACES DE COULEURS
+ #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
+ # Graphics::rgb_to_lch
+ # Algorythme de conversion RGB -> CIE LCH°
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
+ # g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
+ # b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
+ #---------------------------------------------------------------------------
+ """
+ # Conversion RGBtoXYZ
+ gamma = 2.4
+ rgblimit = 0.03928
+
+ if (r > rgblimit):
+ r = ((r + 0.055)/1.055)**gamma
+ else :
+ r = r / 12.92
+
+ if (g > rgblimit) :
+ g = ((g + 0.055)/1.055)**gamma
+ else:
+ g = g / 12.92
+
+ if (b > rgblimit) :
+ b = ((b + 0.055)/1.055)**gamma
+ else:
+ b = b / 12.92
+
+ r *= 100
+ g *= 100
+ b *= 100
+
+ X = (0.4124 * r) + (0.3576 * g) + (0.1805 * b)
+ Y = (0.2126 * r) + (0.7152 * g) + (0.0722 * b)
+ Z = (0.0193 * r) + (0.1192 * g) + (0.9505 * b)
+
+ # Conversion XYZtoLab
+ gamma = 1/3
+ (L, A, B) = 0, 0, 0
+
+ if (Y == 0) :
+ (L, A, B) = (0, 0, 0)
+ else :
+ #Utilisation des constantes white point (variables globale)
+ (Xs, Ys, Zs) = (X/Xw, Y/Yw, Z/Zw)
+
+
+ if (Xs > 0.008856) :
+ Xs = Xs**gamma
+ else :
+ Xs = (7.787 * Xs) + (16/116)
+
+ if (Ys > 0.008856) :
+ Ys = Ys**gamma
+ else :
+ Ys = (7.787 * Ys) + (16/116)
+
+ if (Zs > 0.008856) :
+ Zs = Zs**gamma
+ else :
+ Zs = (7.787 * Zs) + (16/116)
+
+ L = (116.0 * Ys) - 16.0
+
+ A = 500 * (Xs - Ys)
+ B = 200 * (Ys - Zs)
+
+ # conversion LabtoLCH
+ (C, H) = 0, 0
+
+
+ if (A == 0) :
+ H = 0
+ else :
+ H = atan2(B, A)
+
+ if (H > 0) :
+ H = (H / pi) * 180
+
+ else :
+ H = 360 - ( abs(H) / pi) * 180
+
+
+
+ C = sqrt(A**2 + B**2)
+
+ return (L, C, H)
+
+def lch_to_rgb (L, C, H) :
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::lch_to_rgb
+ # Algorythme de conversion CIE L*CH -> RGB
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # L : <pourcent> (de 0 à 1) valeur de la composante luminosité
+ # de la couleur CIE LCH
+ # C : <pourcent> (de 0 à 1) valeur de la composante saturation
+ # de la couleur CIE LCH
+ # H : <pourcent> (de 0 à 1) valeur de la composante teinte
+ # de la couleur CIE LCH
+ #---------------------------------------------------------------------------
+ """
+ (a, b) = 0, 0
+
+ # Conversion LCHtoLab
+ a = cos( radians(H)) * C
+ b = sin( radians(H)) * C
+
+ # Conversion LabtoXYZ
+ gamma = 3
+ (X, Y, Z) = 0, 0, 0
+
+ Ys = (L + 16.0) / 116.0
+ Xs = (a / 500) + Ys
+ Zs = Ys - (b / 200)
+
+ if ((Ys**gamma) > 0.008856) :
+ Ys = Ys**gamma
+ else :
+ Ys = (Ys - 16 / 116) / 7.787
+
+ if ((Xs**gamma) > 0.008856) :
+ Xs = Xs**gamma
+ else :
+ Xs = (Xs - 16 / 116) / 7.787
+
+ if ((Zs**gamma) > 0.008856) :
+ Zs = Zs**gamma
+ else :
+ Zs = (Zs - 16 / 116) / 7.787
+
+
+ X = Xw * Xs
+ Y = Yw * Ys
+ Z = Zw * Zs
+
+ # Conversion XYZtoRGB
+ gamma = 1/2.4
+ rgblimit = 0.00304
+ (R, G, B) = (0, 0, 0)
+
+ X /= 100
+ Y /= 100
+ Z /= 100
+
+ R = (3.2410 * X) + (-1.5374 * Y) + (-0.4986 * Z)
+ G = (-0.9692 * X) + (1.8760 * Y) + (0.0416 * Z)
+ B = (0.0556 * X) + (-0.2040 * Y) + (1.0570 * Z)
+
+ if (R > rgblimit) :
+ R = (1.055 * (R**gamma)) - 0.055
+ else :
+ R = (12.92 * R)
+
+ if (G > rgblimit) :
+ G = (1.055 * (G**gamma)) - 0.055
+ else :
+ G = (12.92 * G)
+
+ if (B > rgblimit) :
+ B = (1.055 * (B**gamma)) - 0.055
+ else :
+ B = (12.92 * B)
+
+ if (R < 0) :
+ R = 0
+ elif (R > 1.0) :
+ R = 1.0
+ else :
+ R = _trunc(R, 5)
+
+ if (G < 0) :
+ G = 0
+ elif (G > 1.0) :
+ G = 1.0
+ else :
+ G = _trunc(G, 5)
+
+ if (B < 0) :
+ B = 0
+ elif (B > 1.0) :
+ B = 1.0
+ else :
+ B = _trunc(B, 5)
+
+ return (R, G, B)
+
+def rgb_to_hls(r, g, b):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::rgb_to_hls
+ # Algorythme de conversion RGB -> HLS
+ #---------------------------------------------------------------------------
+ # r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
+ # g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
+ # b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
+ #---------------------------------------------------------------------------
+ """
+ H, L, S = 0, 0, 0
+ minv, maxv, diffv = 0, 0, 0
+ maxv = max(r, g, b)
+ minv = min(r, g, b)
+
+ # calcul de la luminosité
+ L = (maxv + minv) / 2
+
+ # calcul de la saturation
+ if (maxv == minv) :
+ # couleur a-chromatique (gris) r = g = b
+ S = 0
+ H = None
+ return [H, L, S]
+
+ # couleurs "Chromatiques" --------------------
+
+ # calcul de la saturation
+ if (L <= 0.5) :
+ S = (maxv - minv) / (maxv + minv)
+
+ else :
+ S = (maxv - minv) / (2 - maxv - minv)
+
+ # calcul de la teinte
+ diffv = maxv - minv
+
+ if (r == maxv) :
+ # couleur entre jaune et magenta
+ H = (g - b) / diffv
+
+ elif (g == maxv) :
+ # couleur entre cyan et jaune
+ H = 2 + (b - r) / diffv
+
+ elif (b == maxv) :
+ # couleur entre magenta et cyan
+ H = 4 + (r - g) / diffv
+
+ # Conversion en degrés
+ H *= 60
+
+ # pour éviter une valeur négative
+ if (H < 0) :
+ H += 360
+
+ return [H, L, S]
+
+def hls_to_rgb (H, L, S):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::hls_to_rgb
+ # Algorythme de conversion HLS -> RGB
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # H : <pourcent>(de 0 à 1) valeur de la composante teinte de la couleur HLS
+ # L : <pourcent>(de 0 à 1) valeur de la composante luminosité de la
+ # couleur HLS
+ # S : <pourcent>(de 0 à 1) valeur de la composante saturation
+ # de la couleur HLS
+ #---------------------------------------------------------------------------
+ """
+ (R, G, B) = 0, 0, 0
+ (p1, p2) = 0, 0
+
+
+ if (L <= 0.5) :
+ p2 = L + (L * S)
+
+ else :
+ p2 = L + S - (L * S)
+
+ p1 = 2.0 * L - p2
+
+ if (S == 0) :
+ # couleur a-chromatique (gris)
+ # R = G = B = L
+ R = L
+ G = L
+ B = L
+
+ else :
+ # couleurs "Chromatiques"
+ R = hls_value(p1, p2, H + 120)
+ G = hls_value(p1, p2, H)
+ B = hls_value(p1, p2, H - 120)
+
+ return [R, G, B]
+
+def hls_value(q1, q2, hue):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::hls_value (sous fonction interne hls_to_rgb)
+ #---------------------------------------------------------------------------
+ """
+ value = None
+
+ hue = hue % 360
+
+ if (hue < 60) :
+ value = q1 + (q2 - q1) * hue / 60
+
+ elif (hue < 180) :
+ value = q2
+
+ elif (hue < 240) :
+ value = q1 + (q2 - q1) * (240 - hue) / 60
+
+ else :
+ value = q1
+
+ return value
+
+def hexargbcolor(r, g, b, a = None):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::hexargbcolor
+ # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
+ #---------------------------------------------------------------------------
+ """
+ hexacolor = "#%02x%02x%02x"% (r, g, b)
+ if ( a is not None ):
+ hexacolor = "%s;%d"% (hexacolor, a)
+ return hexacolor
+
+
+
+def hexa2rgb(hexastr):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::hexa2rgb
+ # conversion d'une couleur au format Zinc '#ffffff' en RGB (255,255,255)
+ #---------------------------------------------------------------------------
+ """
+ r, g, b = 0, 0, 0
+ regex = re.compile("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$")
+ res = regex.match(hexastr)
+ if res is not None :
+ r = int(res.group(1), 16)
+ g = int(res.group(2), 16)
+ b = int(res.group(3), 16)
+ return (r/255, g/255, b/255)
+ else :
+ raise ValueError("Not a hexa color")
+
+def get_pattern (filename, **options):
+ """
+ #---------------------------------------------------------------------------
+ # RESOURCES GRAPHIQUES PATTERNS, TEXTURES, IMAGES, GRADIENTS, COULEURS...
+ #---------------------------------------------------------------------------
+ #---------------------------------------------------------------------------
+ # Graphics::get_pattern
+ # retourne la ressource bitmap en l'initialisant si première utilisation
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # filename : nom du fichier bitmap pattern
+ # options
+ # -storage : <hastable> référence de la table de stockage de patterns
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('storage')):
+ table = options['storage']
+ else :
+ table = bitmaps
+ if (not table.has_key(filename)) :
+ bitmap = "@%s"% (find_inc(filename))
+ table[filename] = bitmap
+ return table[filename]
+
+def get_texture(widget, filename, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::get_texture
+ # retourne l'image de texture en l'initialisant si première utilisation
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # filename : nom du fichier texture
+ # options
+ # -storage : <hastable> référence de la table de stockage de textures
+ #---------------------------------------------------------------------------
+ """
+ if (options.has_key('storage')):
+ table = options['storage']
+ else :
+ table = textures
+ return get_image(widget, filename, storage = table)
+
+class FileNotFound (Exception):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::FileNotFound
+ # Classe d'exception levée lorsqu'un fichier n'est pas trouvé
+ # paramètres :
+ # filename : nom du fichier
+ #---------------------------------------------------------------------------
+ """
+ def __init__(self, filename):
+ Exception.__init__(self, "File %s not Found"%(filename))
+
+def find_inc(name):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::find_inc
+ # recherche le fichier dans les répertoires de PYTHONPATH
+ #---------------------------------------------------------------------------
+ """
+ import sys
+ import os.path
+ for path in sys.path:
+ tfile = os.path.join(path, name)
+ if (os.path.isfile(tfile)):
+ return tfile
+ raise FileNotFound(name)
+
+
+def get_image(zinc, filename, storage = {}):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::get_image
+ # retourne la ressource image en l'initialisant si première utilisation
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # filename : nom du fichier image
+ # options
+ # storage : <hastable> référence de la table de stockage d'images
+ #---------------------------------------------------------------------------
+ """
+ if (not storage.has_key(filename)):
+ im = PIL.Image.open(find_inc(filename))
+ #Cela marche uniquement si Tkinter.Tk a une instance
+ image = PIL.ImageTk.PhotoImage(im)
+ storage[filename] = image
+ return storage[filename]
+
+def init_pixmaps(widget, *pixfiles, **options):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::init_pixmaps
+ # initialise une liste de fichier image
+ #---------------------------------------------------------------------------
+ # paramètres :
+ # widget : <widget> identifiant du widget zinc
+ # filenames : <filenameList> list des noms des fichier image
+ # options
+ # storage : <hastable> référence de la table de stockage d'images
+ #---------------------------------------------------------------------------
+ """
+ imgs = []
+ for pixfile in pixfiles:
+ imgs.append(get_image(widget, pixfile, **options))
+ return imgs
+
+def _trunc(f, n):
+ """
+ #---------------------------------------------------------------------------
+ # Graphics::_trunc
+ # fonction interne de troncature des nombres: n = position décimale
+ #---------------------------------------------------------------------------
+ """
+ import fpformat
+ return fpformat.fix(f, n)
+
+#Local Variables:
+#mode : python
+#tab-width: 4
+#end:
diff --git a/debian/zinc-python/usr/lib/python2.7/dist-packages/python_zinc-1.0.egg-info b/debian/zinc-python/usr/lib/python2.7/dist-packages/python_zinc-1.0.egg-info
new file mode 100755
index 0000000..b2397df
--- /dev/null
+++ b/debian/zinc-python/usr/lib/python2.7/dist-packages/python_zinc-1.0.egg-info
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: python-zinc
+Version: 1.0
+Summary: Zinc for Python
+Home-page: http://www.tkzinc.org
+Author: Guillaume Vidon
+Author-email: vidon at ath.cena.fr
+License: GPL
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/debian/zinc-python/usr/share/doc/zinc-python/changelog.gz b/debian/zinc-python/usr/share/doc/zinc-python/changelog.gz
new file mode 100755
index 0000000..b71ea31
--- /dev/null
+++ b/debian/zinc-python/usr/share/doc/zinc-python/changelog.gz
Binary files differ
diff --git a/debian/zinc-python/usr/share/doc/zinc-python/copyright b/debian/zinc-python/usr/share/doc/zinc-python/copyright
new file mode 100755
index 0000000..af377f5
--- /dev/null
+++ b/debian/zinc-python/usr/share/doc/zinc-python/copyright
@@ -0,0 +1,20 @@
+This package was debianized by Patrick Lecoanet lecoanet@ath.cena.fr on
+Wed, 25 Feb 1998 14:11:43 +0100.
+
+Copyright:
+
+ Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/paper.gif b/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/paper.gif
new file mode 100755
index 0000000..3247d35
--- /dev/null
+++ b/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/paper.gif
Binary files differ
diff --git a/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/testGraphics.py b/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/testGraphics.py
new file mode 100755
index 0000000..0b27b34
--- /dev/null
+++ b/debian/zinc-python/usr/share/doc/zinc-python/demos/Graphics/testGraphics.py
@@ -0,0 +1,1864 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+#-----------------------------------------------------------------------------------
+#
+# testGraphics.py
+# Fichier test du module Graphics
+#
+# Authors: Jean-Luc Vinot <vinot@cena.fr> Guilaume Vidon <vidon@ath.cena.fr>
+#
+# $Id: testGraphics.py 1698 2005-06-13 00:26:40Z vidon $
+#-----------------------------------------------------------------------------------
+import sys
+
+try :
+ import IPython.ultraTB
+ sys.excepthook = IPython.ultraTB.FormattedTB(mode = 'Verbose',
+ color_scheme = 'Linux',
+ call_pdb = 1)
+except ImportError:
+ pass
+
+VERSION = "1.13"
+
+import Tkinter
+import Zinc
+import Zinc.pictorial as pictorial
+from Zinc.geometry import *
+from Zinc.graphics import build_zinc_item, tabbox_coords, lpts2coords, coords2lpts
+import math
+import getopt
+
+currenttransfo = None
+previousangle = 0
+rotate_angle = .1
+zoomfactor = .1
+curview = None
+dx, dy = 0, 0
+
+tabanchor = 'n'
+tabalign = 'left'
+
+font_9b = '7x13bold'
+# the original font is not standard, even if it is fully free:
+# font_9b = '-cenapii-bleriot mini-bold-r-normal--9-90-75-75-p-75-iso8859-15'
+
+gradset = {
+ 'boitonglet' : '=axial 0|#ff7777|#ffff99',
+ 'roundrect1' : '=axial 270|#a7ffa7;70 0|#ffffff;90 5|#00bd00;80 8|#b7ffb7;50 80|#ffffff;70 91|#00ac00;70 95|#006700;60 100',
+ 'roundrect2' : '=axial 270|#00bd00;80 |#d7ffd7;60',
+ 'roundrect3' : '=axial 270|#00bd00;100 0|#ffffff;100 14|#ffffff;100 16|#00bd00;90 25|#b7ffb7;60 100',
+ 'roundrect4' : '=axial 0|#00bd00;100 0|#ffffff;100 20|#00bd00;50 30|#00bd00;90 80|#b7ffb7;60 100',
+ 'roundrect4ed' : '=path 48 48|#e7ffe7;20 0 70|#007900;20',
+ 'roundcurve2' : '=axial 270|#d7ffd7;60|#7777ff;80',
+ 'roundcurve1' : '=axial 270|#2222ff;80 |#d7ffd7;60',
+ 'roundcurve' : '=axial 270|#7777ff;80 |#d7ffd7;60',
+ 'roundpolyg' : '=radial -15 -20|#ffb7b7;50|#bd6622;90',
+ 'rpolyline' : '=axial 90|#ffff77;80 |#ff7700;60',
+ 'pushbtn1' : '=axial 0|#cccccc;100 0|#ffffff;100 10|#5a5a6a;100 80|#aaaadd;100 100',
+ 'pushbtn2' : '=axial 270|#ccccff;100 0|#ffffff;100 10|#5a5a7a;100 80|#bbbbee;100 100',
+ 'pushbtn3' : '=radial -15 -15|#ffffff;100 0|#333344;100 100',
+ 'pushbtn4' : '=axial 270|#ccccff;100 0|#ffffff;100 10|#7a7a9a;100 80|#bbbbee;100 100',
+ 'conical_edge' : '=conical 0 0 -45|#ffffff;100 0|#888899;100 30|#555566;100 50|#888899;100 70|#ffffff;100 100',
+ 'conical_ext' : '=conical 0 0 135|#ffffff;100 0|#777788;100 30|#444455;100 50|#777788;100 70|#ffffff;100 100',
+ 'pushbtn_edge' : '=axial 140|#ffffff;100 0|#555566;100 100',
+ 'pushbtn_edge2' : '=axial 92|#ffffff;100 0|#555566;100 100',
+ 'logoshape2' : '=axial 270|#ffffff|#7192aa',
+ 'logopoint2' : '=radial -20 -20|#ffffff 0|#f70000 48|#900000 80|#ab0000 100',
+ 'logoptshad2' : '=path 0 0|#770000;64 0|#770000;70 78|#770000;0 100'}
+
+
+# contenu des pages exemples
+pagesconf = {'Rectangle' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 155),
+ 'params' : {'font' : font_9b,
+ 'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
+ 'color' : '#2222cc',
+ },
+ },
+ # roudedrectangle simple + radius 20
+ 'rr1' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((-200, 30), (50, 130)),
+ 'radius' : 20,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('move'),
+ },
+ },
+ # roudedrectangle 'carré' (radius automatique)
+ 'rr2' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((-250, -100), (-90, 60)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect1',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ },
+ # cas particulier -> hippodrome (radius = h/2)
+ 'rr3' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((-30, 80), (130, 160)),
+ 'radius' : 40,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect3',
+ 'linewidth' : 4,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ },
+ 'rr4a' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((-30, -60), (110, 10)),
+ 'radius' : 40,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect3',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ 'corners' : (1, 0, 1, 0),
+ },
+ 'rr4b' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((118, -68), (220, -132)),
+ 'radius' : 40,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect3',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move',),
+ },
+ 'corners' : (1, 0, 1, 0),
+ },
+ 'rr4c' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((118, -60), (190, 30)),
+ 'radius' : 40,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect3',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move',),
+ },
+ 'corners' : (0, 1, 0, 1),
+ },
+ 'rr4d' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((40, -152), (110, -68)),
+ 'radius' : 40,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect3',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ 'corners' : (0, 1, 0, 1),
+ },
+ 'gr8' : {'itemtype' : 'group',
+ 'coords' : (0, 0),
+ 'params' : {'priority' : 10,
+ 'tags' : ('move'),
+ 'atomic' : 1,
+ },
+ 'items' : {'edge' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((174, -36), (266, 146)),
+ 'radius' : 26,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect4ed',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 20,
+ },
+ },
+ 'top' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((180, -30), (260, 53)),
+ 'parentgroup' : 'gr8',
+ 'radius' : 20,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect4',
+ 'linewidth' : 2.5,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ },
+ 'corners' : (1, 0, 0, 1),
+ },
+ 'topico' : {'itemtype' : 'curve',
+ 'parentgroup' : 'gr8',
+ 'coords' : ((220, -10), (200, 30),(240, 30)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#ffff00;80',
+ 'linewidth' : 1,
+ 'linecolor' : '#007900;80',
+ 'priority' : 50,
+ },
+ },
+ 'bottom' : {'itemtype' : 'roundedrectangle',
+ 'parentgroup' : 'gr8',
+ 'coords' : ((180, 57), (260, 140)),
+ 'radius' : 20,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundrect4',
+ 'linewidth' : 2.5,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ },
+ 'corners' : (0, 1, 1, 0),
+ },
+ 'bottomico' : {'itemtype' : 'curve',
+ 'parentgroup' : 'gr8',
+ 'coords' : ((220, 120),(240, 80),(200, 80)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#ffff00;80',
+ 'linewidth' : 1,
+ 'linecolor' : '#007900;80',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+ },
+ 'Hippodrome' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 165),
+ 'params' : {'font' : font_9b,
+ 'text' : "Click hippo Buttons with mouse button 1.\n",
+ 'color' : '#2222cc',
+ },
+ },
+ 'hp1' : {'itemtype' : 'group',
+ 'coords' : (-163, -40),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-46, -86), (46, 86)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn_edge',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 10,
+ },
+ },
+ 'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, -80), (40, 80)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn1',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b1','pushbtn'),
+ },
+ },
+ },
+ },
+ 'hp2' : {'itemtype' : 'group',
+ 'coords' : (-40, -40),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-46, -86), (46, 86)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn_edge',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 10,
+ },
+ },
+ 'formT' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, -80), (40, -28)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn1',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b2t','pushbtn'),
+ },
+ 'orientation' : 'vertical',
+ 'trunc' : 'bottom',
+ },
+ 'formC' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, -26.5), (40, 26.5)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn1',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b2c','pushbtn'),
+ },
+ 'trunc' : 'both',
+ },
+ 'formB' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, 28), (40, 80)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn1',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b2b','pushbtn'),
+ },
+ 'orientation' : 'vertical',
+ 'trunc' : 'top',
+ },
+ },
+ },
+ 'hp3edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-204, 96), (204, 144)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn_edge2',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 10,
+ },
+ },
+ 'hp3g' : {'itemtype' : 'group',
+ 'coords' : (-160, 120),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, -20), (40, 20)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b3g', 'pushbtn'),
+ },
+ 'trunc' : 'right',
+ },
+ 'ico' : {'itemtype' : 'curve',
+ 'coords' : ((-20, 0), (-4, 8), (-4, -8)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#000000',
+ 'linewidth' : 1,
+ 'linecolor' : '#aaaaaa',
+ 'relief' : 'raised',
+ 'priority' : 30,
+ 'tags' : ('b3g', 'pushbtn', 'ico'),
+ },
+ 'contours' : [['add',-1,((0, 0),(16, 8),(16, -8))]]
+ },
+ },
+ },
+ 'hp3c1' : {'itemtype' : 'group',
+ 'coords' : (-80, 120),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-38, -20), (39, 20)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b3c1', 'pushbtn'),
+ },
+ 'trunc' : 'both',
+ },
+ 'ico' : {'itemtype' : 'curve',
+ 'coords' : ((-8, 0), (8, 8), (8, -8)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#000000',
+ 'linewidth' : 1,
+ 'linecolor' : '#aaaaaa',
+ 'priority' : 30,
+ 'relief' : 'raised',
+ 'tags' : ('b3c1','pushbtn','ico'),
+ },
+ },
+ },
+ },
+ 'hp3c2' : {'itemtype' : 'group',
+ 'coords' : (0, 120),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-39, -20), (39, 20)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b3c2', 'pushbtn'),
+ },
+ 'trunc' : 'both',
+ },
+ 'ico' : {'itemtype' : 'rectangle',
+ 'coords' : ((-6, -6), (6, 6)),
+ 'params' : {'filled' : 1,
+ 'fillcolor' : '#000000',
+ 'linewidth' : 1,
+ 'linecolor' : '#aaaaaa',
+ 'priority' : 30,
+ 'tags' : ('b3c2', 'pushbtn', 'ico'),
+ },
+ },
+ },
+ },
+ 'hp3C3' : {'itemtype' : 'group',
+ 'coords' : (80, 120),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-39, -20), (39, 20)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b3c3', 'pushbtn'),
+ },
+ 'trunc' : 'both',
+ },
+ 'ico' : {'itemtype' : 'curve',
+ 'coords' : ((8, 0), (-8, -8), (-8, 8)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#000000',
+ 'linewidth' : 1,
+ 'linecolor' : '#aaaaaa',
+ 'priority' : 30,
+ 'relief' : 'raised',
+ 'tags' : ('b3c3', 'pushbtn', 'ico'),
+ },
+ },
+ },
+ },
+
+ 'hp3D' : {'itemtype' : 'group',
+ 'coords' : (160, 120),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-40, -20), (40, 20)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn2',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b3d', 'pushbtn'),
+ },
+ 'trunc' : 'left',
+ },
+ 'ico' : {'itemtype' : 'curve',
+ 'coords' : ((20, 0), (4, -8), (4, 8)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#000000',
+ 'linewidth' : 1,
+ 'linecolor' : '#aaaaaa',
+ 'priority' : 30,
+ 'relief' : 'raised',
+ 'tags' : ('b3d', 'pushbtn', 'ico'),
+ },
+ 'contours' : [['add', -1, ((0,0), (-16, -8), (-16, 8))]],
+ },
+ },
+ },
+
+ 'hp4a' : {'itemtype' : 'group',
+ 'coords' : (48, -97),
+ 'params' : {'priority' : 40,
+ },
+ 'repeat' : {'num' : 2,
+ 'dxy' : (0, 64),
+ },
+ 'items' : {'edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-29, -29), (29, 29)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn_edge',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 0,
+ },
+ },
+ 'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-24, -24), (24, 24)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn3',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('b4a','pushbtn'),
+ },
+ },
+ },
+ },
+
+ 'hp4b' : {'itemtype' : 'group',
+ 'coords' : (145, -65),
+ 'params' : {'priority' : 40,
+ },
+ 'items' : {'edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-60, -60), (60, 60)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'conical_edge',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 0,
+ },
+ },
+ 'ext' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-53, -53), (53, 53)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'conical_ext',
+ 'linewidth' : 3,
+ 'linecolor' : '#000000',
+ 'priority' : 10,
+ 'tags' : ('b4b','pushbtn'),
+ },
+ },
+ 'int' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-41, -41), (40, 40)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '=path 10 10|#ffffff 0|#ccccd0 50|#99999f 80|#99999f;0 100',
+ 'linewidth' : 0,
+ 'linecolor' : '#cccccc;80',
+ 'priority' : 30,
+ 'tags' : ('b4b','pushbtn'),
+ },
+ },
+ },
+ },
+
+ 'hp5' : {'itemtype' : 'group',
+ 'coords' : (60, 25),
+ 'params' : {'priority' : 40,
+ },
+ 'rotate' : 30,
+ 'repeat' : {'num' : 4,
+ 'dxy' : (45, 0),
+ },
+ 'items' : {'edge' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-19, -34), (19, 34)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn_edge',
+ 'linewidth' : 1,
+ 'linecolor' : '#ffffff',
+ 'priority' : 10,
+ },
+ },
+ 'form' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-15, -30), (15, 30)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn1',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('b5', 'pushbtn'),
+ },
+ },
+ },
+ },
+ },
+
+ 'Polygone' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 160),
+ 'params' : {'font' : font_9b,
+ 'text' : "Click and Drag inside Polygons for rotate them\nEscape key reset transfos.",
+ 'color' : '#2222cc',
+ },
+ },
+ 'triangle' : {'itemtype' : 'group',
+ 'coords' : (-215, -95),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 3,
+ 'radius' : 78,
+ 'corner_radius' : 10,
+ 'startangle' : 90,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p1', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Triangle",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'carre' : {'itemtype' : 'group',
+ 'coords' : (-80, -75),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 4,
+ 'radius' : 70,
+ 'corner_radius' : 10,
+ 'startangle' : 90,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p2', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Carré",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'pentagone' : {'itemtype' : 'group',
+ 'coords' : (65, -75),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 5,
+ 'radius' : 70,
+ 'corner_radius' : 10,
+ 'startangle' : 270,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p3', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Pentagone",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'hexagone' : {'itemtype' : 'group',
+ 'coords' : (210, -75),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 6,
+ 'radius' : 68,
+ 'corner_radius' : 10,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p4', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Hexagone",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'heptagone' : {'itemtype' : 'group',
+ 'coords' : (-215, 85),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 7,
+ 'radius' : 64,
+ 'corner_radius' : 10,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p5', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Heptagone",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+
+ 'octogone' : {'itemtype' : 'group',
+ 'coords' : (-76, 85),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 8,
+ 'radius' : 64,
+ 'corner_radius' : 10,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p6', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Octogone",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'petagone' : {'itemtype' : 'group',
+ 'coords' : (66, 85),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 32,
+ 'radius' : 64,
+ 'corner_radius' : 10,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p7', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "32 cotés...",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+
+ 'etoile' : {'itemtype' : 'group',
+ 'coords' : (210, 85),
+ 'items' : {'form' : {'itemtype' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 5,
+ 'radius' : 92,
+ 'inner_radius' : 36,
+ 'corner_radius' : 10,
+ 'startangle' : 270,
+ 'corners' : (0, 1, 0, 1, 0, 1, 0, 1, 0, 1),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundpolyg',
+ 'linewidth' : 2,
+ 'linecolor' : '#330000',
+ 'priority' : 20,
+ 'tags' : ('p8', 'poly'),
+ },
+ },
+ 'text' : {'itemtype' : 'text',
+ 'coords' : (0, -6),
+ 'params' : {'font' : font_9b,
+ 'text' : "Etoile",
+ 'anchor' : 'n',
+ 'alignment' : 'center',
+ 'color' : '#660000',
+ 'priority' : 50,
+ },
+ },
+ },
+ },
+ },
+
+ 'Polyline' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 155),
+ 'params' : {'font' : font_9b,
+ 'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
+ 'color' : '#2222cc',
+ },
+ },
+ 'a' : {'itemtype' : 'polyline',
+ 'coords' : ((-200, -115), (-200, -100), (-218, -115), (-280, -115), (-280, -16),
+ (-218, -16), (-200, -31), (-200, -17.5), (-150, -17.5), (-150,-115)),
+ 'corners_radius' : (0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'visible' : 1,
+ 'fillcolor' : 'rpolyline',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 50,
+ 'tags' : ('move'),
+ },
+ 'contours' : [['add', -1, ((-230, -80), (-230, -50), (-200, -50), (-200, -80)),15]],
+ },
+ 'b' : {'itemtype' : 'polyline',
+ 'coords' : ((-138, -150), (-138, -17.5), (-88, -17.5), (-88, -31), (-70, -16),
+ (-8, -16), (-8, -115), (-70, -115), (-88, -100), (-88, -150)),
+ 'corners_radius' : (0, 0, 0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'visible' : 1,
+ 'fillcolor' : 'rpolyline',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 50,
+ 'tags' : ('move'),
+ },
+ 'contours' : [['add', -1, ((-88, -80), (-88, -50), (-58, -50), (-58, -80)), 15]],
+ },
+ 'c' : {'itemtype' : 'polyline',
+ 'coords' : ((80, -76), (80, -110), (60, -115), (0, -115), (0, -16),
+ (60, -16), (80, -21), (80, -57), (50, -47), (50, -86)),
+ 'corners_radius' : (0, 0, 70, 47, 47, 70, 0, 0, 14, 14, 0, 0, 0,0 ),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'visible' : 1,
+ 'fillcolor' : 'rpolyline',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 50,
+ 'tags' : ('move'),
+ },
+ },
+ 'spirale' : {'itemtype' : 'polyline',
+ 'coords' : ((215, -144), (139, -144), (139, 0), (268, 0), (268, -116),
+ (162.5, -116), (162.5, -21), (248, -21), (248, -96), (183, -96),
+ (183, -40), (231,-40), (231, -80), (199, -80), (199, -55), (215, -55)),
+ 'corners_radius' : (0, 76, 68, 61, 55, 50, 45, 40, 35, 30, 26, 22, 18, 14, 11),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'visible' : 1,
+ 'fillcolor' : 'rpolyline',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 50,
+ 'tags' : ('move'),
+ },
+ },
+ 'logo' : {'itemtype' : 'group',
+ 'coords' : (0, 0),
+ 'params' : {'priority' : 30,
+ 'atomic' : 1,
+ 'tags' : ('move'),
+ },
+ 'items' : {'tkzinc' : {'itemtype' : 'polyline',
+ 'coords' : ((-150,10), (-44,10), (-44,68), (-28,51), (6,51),
+ (-19,79), (3,109), (53,51), (5,51), (5,10), (140,10),
+ (52,115), (96,115), (96,47), (196,47), (196,158),
+ (155,158), (155,89), (139,89), (139,160), (101, 160),
+ (101,132), (85,132), (85,160), (-42,160), (-2,115),
+ (-30,115), (-46,91), (-46,115), (-76,115), (-76,51),
+ (-98,51), (-98,115), (-130,115), (-130,51), (-150, 51)),
+ 'corners_radius' : [0,0,0,0,0,0,0,0,0,0,30,0,0,50,50,
+ 0,0,8,8,0,0,8,8,0,27],
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'visible' : 1,
+ 'fillcolor' : 'logoshape2',
+ 'linewidth' : 2.5,
+ 'linecolor' : '#000000',
+ 'priority' : 10,
+ 'fillrule' : 'nonzero',
+ },
+
+ 'contours' : [['add', 1, ((245,88), (245,47), (190,47), (190,158),
+ (259,158), (259,117), (230,117), (230,88)),
+ 5, None, (0,0,55,55,0,0,15,15)]],
+ },
+ 'shad' : {'itemtype' : 'arc',
+ 'coords' : ((75, 91), (115,131)),
+ 'params' : {'priority' : 20,
+ 'filled' : 1,
+ 'linewidth' : 0,
+ 'fillcolor' : 'logoptshad2',
+ 'closed' : 1,
+ },
+ },
+ 'point' : {'itemtype' : 'arc',
+ 'coords' : ((70, 86), (110,126)),
+ 'params' : {'priority' : 50,
+ 'filled' : 1,
+ 'linewidth' : 1,
+ 'linecolor' : '#a10000',
+ 'fillcolor' : 'logopoint2',
+ 'closed' : 1,
+ },
+ },
+ },
+ },
+ },
+
+ 'MultiContours' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 155),
+ 'params' : {'font' : font_9b,
+ 'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
+ 'color' : '#2222cc',
+ },
+ },
+ 'mc1' : {'itemtype' : 'roundedcurve',
+ 'coords' : ((-30, -170), (-130, 0), (70, 0)),
+ 'radius' : 14,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundcurve2',
+ 'linewidth' : 1,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('move'),
+ 'fillrule' : 'odd',
+ },
+ 'contours' : [['add', 1,((-30,-138), (-100,-18), (40,-18)), 8],
+ ['add', 1,((-30,-130), ( -92,-22), (32,-22)), 5],
+ ['add', 1,((-30,-100), ( -68,-36), (8,-36)), 5],
+ ['add', 1,((-30, -92), ( -60,-40), (0,-40)), 3],],
+ },
+ 'mc2' : {'itemtype' : 'polyline',
+ 'coords' : ((-250,-80), (-240,-10), (-285,-10), (-285,80),
+ (-250, 80), (-250, 40), (-170, 40), (-170,80),
+ (-100,80), (-100,40), (-20,40), (-20,80), (30,80),
+ (-10, 0), (-74, -10), (-110, -80)),
+ 'corners_radius' : (24,4, 40, 20, 0, 40, 40, 0, 0, 40, 40, 0, 30, 75, 0, 104),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundcurve1',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ 'contours' : [['add',-1,((-240,-72), (-230,0), (-169,0), (-185, -72)),
+ 0, None, (16, 16, 0, 0)],
+ ['add', -1, ((-175,-72), (-159,0), (-78,0), (-116, -72)),
+ 0, None, (0, 0, 8, 88)],
+ ['add', 1, ((-245,45), (-245,115), (-175,115), (-175, 45)),
+ 35],
+ ['add', -1, ((-225,65), (-225,95), (-195,95), (-195, 65)),
+ 15],
+ ['add', 1, ((-95,45), (-95,115), (-25,115), (-25, 45)),
+ 35],
+ ['add', -1, ((-75,65), (-75,95), (-45,95), (-45, 65)),
+ 15],
+ ],
+ },
+ 'mc3' : {'itemtype' : 'roundedcurve',
+ 'coords' : ((-10, 170), (256, 170), (312, 60), (48, 60)),
+ 'radius' : 34,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundcurve2',
+ 'linewidth' : 2.5,
+ 'linecolor' : '#000000',
+ 'priority' : 40,
+ 'tags' : ('move'),
+ },
+ 'contours' : [['add', -1, ((58, 62), (12, 144), (60, 172), (104, 88)), 27],
+ ['add', 1, ((48, 77), (48, 119), (90, 119), (90, 77)), 21],
+ ['add', -1, ((244, 58), (198, 140), (246, 168), (290, 84)), 27],
+ ['add', 1, ((213, 110), (213, 152), (255, 152), (255, 110)), 21],
+ ['add', -1, ((150, 60), (150, 170), (160, 170), (160, 60)), 0]],
+ },
+ 'mc4' : {'itemtype' : 'roundedcurve',
+ 'coords' : ((222, -150), (138, -150), (180, -50), (138, -150),
+ (80, -92), (180, -50), (80, -92), (80, -8),
+ (180, -50), (80, -8), (138, 50), (180, -50),
+ (138, 50), (222, 50), (179.8, -50), (222, 50),
+ (280, -8), (180, -50), (280, -8), (280, -92),
+ (180, -50), (280, -92), (222,-150), (180,-50)),
+ 'radius' : 28,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'roundcurve',
+ 'linewidth' : 2,
+ 'linecolor' : '#000000',
+ 'priority' : 30,
+ 'tags' : ('move'),
+ },
+ 'contours' : [['add', -1, ((160, -70), (160, -30), (200, -30), (200, -70)), 20]],
+ },
+ },
+
+ 'TabBox' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 160),
+ 'params' : {'font' : font_9b,
+ 'text' : "Click on thumbnail to select page\nChange anchor or alignment tabs options with radio buttons.\n",
+ 'color' : '#2222cc',
+ },
+ },
+
+ 'exemple' : {'itemtype' : 'text',
+ 'coords' : (-165, -105),
+ 'params' : {'font' : font_9b,
+ 'text' : "",
+ 'alignment' : 'left',
+ 'anchor' : 'nw',
+ 'color' : '#000000',
+ 'priority' : 500,
+ 'width' : 350,
+ 'tags' : ('div2', 'fontname'),
+ },
+ },
+
+ 'bo1' : {'itemtype' : 'tabbox',
+ 'coords' : ((-240, -160), (240, 100)),
+ 'radius' : 8,
+ 'tabwidth' : 72,
+ 'tabheight' : 28,
+ 'numpages' : 8,
+ 'anchor' : 'n',
+ 'alignment' : 'left',
+ 'overlap' : 3,
+ 'params' : {'closed' : 1,
+ 'priority' : 100,
+ 'filled' : 1,
+ 'fillcolor' : '#ffffff',
+ 'linewidth' : 1.2,
+ 'linecolor' : '#000000',
+ 'tags' : ('div2', 'divider'),
+ },
+ 'tabtitles' : {'text' : ('A', 'B', 'C', 'D', 'E', 'F','G','H'),
+ 'params' : {'text' : 'titre',
+ 'color' : '#2222cc',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 400,
+ 'visible' : 1,
+ },
+ },
+ },
+
+ 'back' : {'itemtype' : 'roundedrectangle',
+ 'coords' : ((-242, -162), (242, 102)),
+ 'radius' : 10,
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '#777777;80',
+ 'linewidth' : 1,
+ 'linecolor' : '#777777;80',
+ },
+ },
+
+ 'anchor' : {'itemtype' : 'text',
+ 'coords' : (-120, 115),
+ 'params' : {'text' : 'tabs anchor',
+ 'color' : '#2222cc',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ },
+ },
+
+ 'anchorN' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-210, 125), (-165, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel1', 'n', 'btn', 'selector'),
+ },
+ 'trunc' : 'right',
+ },
+ 'txtanN' : {'itemtype' : 'text',
+ 'coords' : (-187, 138),
+ 'params' : {'text' : 'N',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel1', 'n', 'btntext', 'selector'),
+ },
+ },
+
+ 'anchorE' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-163, 125), (-120, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel1', 'e', 'btn', 'selector'),
+ },
+ 'trunc' : 'both',
+ },
+ 'txtanE' : {'itemtype' : 'text',
+ 'coords' : (-141.5, 138),
+ 'params' : {'text' : 'E',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel1', 'e', 'btntext', 'selector'),
+ },
+ },
+
+ 'anchorS' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-118, 125), (-75, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel1', 's', 'btn', 'selector'),
+ },
+ 'trunc' : 'both',
+ },
+ 'txtanS' : {'itemtype' : 'text',
+ 'coords' : (-96.5, 138),
+ 'params' : {'text' : 'S',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel1', 's', 'btntext', 'selector'),
+ },
+ },
+ 'anchorW' : {'itemtype' : 'hippodrome',
+ 'coords' : ((-73, 125), (-28, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel1', 'w', 'btn', 'selector'),
+ },
+ 'trunc' : 'left',
+ },
+ 'txtanW' : {'itemtype' : 'text',
+ 'coords' : (-52, 138),
+ 'params' : {'text' : 'W',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel1', 'w', 'btntext', 'selector'),
+ },
+ },
+ 'alignment' : {'itemtype' : 'text',
+ 'coords' : (120, 115),
+ 'params' : {'text' : 'tabs alignment',
+ 'color' : '#2222cc',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ },
+ },
+ 'alignG' : {'itemtype' : 'hippodrome',
+ 'coords' : ((30, 125), (90, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel2', 'left', 'btn', 'selector'),
+ },
+ 'trunc' : 'right',
+ },
+ 'txtalG' : {'itemtype' : 'text',
+ 'coords' : (60, 138),
+ 'params' : {'text' : 'left',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel2', 'left', 'btntext', 'selector'),
+ },
+ },
+ 'alignC' : {'itemtype' : 'hippodrome',
+ 'coords' : ((92, 125), (148, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel2', 'center', 'btn', 'selector'),
+ },
+ 'trunc' : 'both',
+ },
+ 'txtalC' : {'itemtype' : 'text',
+ 'coords' : (120, 138),
+ 'params' : {'text' : 'center',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel2', 'center', 'btntext', 'selector'),
+ },
+ },
+ 'alignD' : {'itemtype' : 'hippodrome',
+ 'coords' : ((150, 125), (210, 151)),
+ 'params' : {'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : 'pushbtn4',
+ 'linewidth' : 1.5,
+ 'linecolor' : '#000000',
+ 'priority' : 20,
+ 'tags' : ('sel2', 'right', 'btn', 'selector'),
+ },
+ 'trunc' : 'left',
+ },
+ 'txtalD' : {'itemtype' : 'text',
+ 'coords' : (180, 138),
+ 'params' : {'text' : 'right',
+ 'color' : '#000000',
+ 'font' : font_9b,
+ 'anchor' : 'center',
+ 'alignment' : 'center',
+ 'priority' : 40,
+ 'tags' : ('sel2', 'right', 'btntext', 'selector'),
+ },
+ },
+ },
+
+ 'PathLine' : {'consigne' : {'itemtype' : 'text',
+ 'coords' : (-285, 155),
+ 'params' : {'font' : font_9b,
+ 'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
+ 'color' : '#2222cc',
+ },
+ },
+ 'pl1' : {'itemtype' : 'pathline',
+ 'metacoords' : {'type' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 12,
+ 'radius' : 200,
+ 'inner_radius' : 100,
+ 'startangle' : -8,
+ },
+ 'linewidth' : 20,
+ 'closed' : 1,
+ 'graduate' : {'type' : 'linear',
+ 'colors' : ('#ff0000', '#ff00ff', '#0000ff', '#00ffff',
+ '#00ff00', '#ffff00', '#ff0000'),
+ },
+ 'params' : {'priority' : 100,
+ 'tags' : ('move'),
+ },
+ },
+
+ 'pl2' : {'itemtype' : 'group',
+ 'coords' : (0, 0),
+ 'params' : {'priority' : 200,
+ 'atomic' : 1,
+ 'tags' : ('move'),
+ },
+ 'items' : {'in' : {'itemtype' : 'pathline',
+ 'coords' : ((30, -60), (-30, -60), (-30, -30),
+ (-60, -30), (-60, 30), (-30, 30),
+ (-30, 60), (30, 60), (30, 30),
+ (60, 30), (60, -30), (30, -30)),
+ 'linewidth' : 16,
+ 'closed' : 1,
+ 'shifting' : 'left',
+ 'graduate' : {'type' : 'transversal',
+ 'colors' : ('#00aa77;100', '#00aa77;0'),
+ },
+ 'params' : {'priority' : 10,
+ },
+ },
+
+ 'out' : {'itemtype' : 'pathline',
+ 'coords' : ((30, -60), (-30, -60), (-30, -30),
+ (-60, -30), (-60, 30), (-30, 30),
+ (-30, 60), (30, 60), (30, 30),
+ (60, 30), (60, -30), (30, -30)),
+ 'linewidth' : 10,
+ 'closed' : 1,
+ 'shifting' : 'in',
+ 'graduate' : {'type' : 'transversal',
+ 'colors' : ('#00aa77;100', '#00aa77;0'),
+ },
+ 'params' : {'priority' : 10,
+ },
+ },
+ },
+ },
+
+ 'pl3' : {'itemtype' : 'group',
+ 'coords' : (0, 0),
+ 'params' : {'priority' : 100,
+ 'atomic' : 1,
+ 'tags' : ('move'),
+ },
+ 'items' : {'back' : {'itemtype' : 'arc',
+ 'coords' : ((-150, -150), (150,150)),
+ 'params' : {'priority' : 10,
+ 'closed' : 1,
+ 'filled' : 1,
+ 'fillcolor' : '=radial 15 15|#ffffff;40|#aaaaff;10',
+ 'linewidth' : 0,
+ },
+ },
+ 'light' : {'itemtype' : 'pathline',
+ 'metacoords' : {'type' : 'polygone',
+ 'coords' : (0, 0),
+ 'numsides' : 30,
+ 'radius' : 150,
+ 'startangle' : 240,
+ },
+ 'linewidth' : 20,
+ 'shifting' : 'in',
+ 'closed' : 1,
+ 'graduate' : {'type' : 'double',
+ 'colors' : (('#ffffff;0', '#222299;0', '#ffffff;0'),
+ ('#ffffff;100', '#222299;70', '#ffffff;100')),
+ },
+ 'params' : {'priority' : 50,
+ },
+ },
+ 'bord' : {'itemtype' : 'arc',
+ 'coords' : ((-150, -150), (150,150)),
+ 'params' : {'priority' : 100,
+ 'closed' : 1,
+ 'filled' : 0,
+ 'linewidth' : 2,
+ 'linecolor' : '#000033;80'
+ },
+ },
+
+ },
+ },
+ }
+ }
+
+
+tabtables = { 'n' : {'numpages' : 8,
+ 'titles' : ('A','B','C','D','E','F','G','H'),
+ 'names' : ('ATOMIC GROUP :', 'BIND COMMAND :', 'CURVE ITEMS :', 'DISPLAY LIST :',
+ 'EVENTS SENSITIVITY :', 'FIT COMMAND :', 'GROUP ITEMS', 'HASTAG COMMAND'),
+ 'texts' : ("It may seem at first that there is a contradiction in this title, but there is not. (...) So groups have a feature, the atomic attribute, that is used to seal a group so that events cannot propagate past it downward. If an item part of an atomic group is under the pointer, TkZinc will try to trigger bindings associated with the atomic group not with the item under the pointer. This improves greatly the metaphor of an indivisible item.",
+ "This widget command is similar to the Tk bind command except that it operates on TkZinc items instead of widgets. Another difference with the bind command is that only mouse and keyboard related events can be specified (such as Enter, Leave, ButtonPress, ButtonRelease, Motion, KeyPress, KeyRelease). The bind manual page is the most accurate place to look for a definition of sequence and command and for a general understanding of how the binding mecanism works.",
+ "Items of type curve display pathes of line segments and/or cubic bezier connected by their end points. A cubic Bezier is defined by four points. The first and last ones are the extremities of the cubic Bezier. The second and the third ones are control point (i.e. they must have a third ``coordinate'' with the value 'c'). If both control points are identical, one may be omitted. As a consequence, it is an error to have more than two succcessive control points or to start or finish a curve with a control point.",
+ "The items are arranged in a display list for each group. The display list imposes a total ordering among its items. The group display lists are connected in a tree identical to the group tree and form a hierarchical display list. The items are drawn by traversing the display list from the least visible item to the most visible one.The search to find the item that should receive an event is done in the opposite direction. In this way, items are drawn according to their relative stacking order and events are dispatched to the top-most item at a given location.",
+ "An item will catch an event if all the following conditions are satisfied: * the item -sensitive must be set to true (this is the default). * the item must be under the pointer location. * the item must be on top of the display list (at the pointer location). Beware that an other item with its -visible set to false DOES catch event before any underneath items. * the item must not be clipped (at the pointer location) * the item must not belong to an atomic group, since an atomic group catchs the event instead of the item.",
+ "This command fits a sequence of Bezier segments on the curve described by the vertices in coordList and returns a list of lists describing the points and control points for the generated segments. All the points on the fitted segments will be within error distance from the given curve. coordList should be either a flat list of an even number of coordinates in x, y order or a list of lists of point coordinates X, Y. The returned list can be directly used to create or change a curve item contour.",
+ "Groups are very powerful items. They have no graphics of their own but are used to bundle items together so that they can be manipulated easily as a whole. Groups can modify in several way how items are displayed and how they react to events. They have many uses in TkZinc. The main usages are to bundle items, to interpose a new coordinate system in a hierarchy of items, to compose some specific attributes, to apply a clipping to their children items, to manage display",
+ "This command returns a boolean telling if the item specified by tagOrId has the specified tag. If more than one item is named by tagOrId, then the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised.",
+ ),
+ },
+ 'e' : {'numpages' : 5,
+ 'titles' : ('I', 'J', 'K', 'L', 'M'),
+ 'names' : ('ITEM IDS', 'JOINSTYLE ATTRIBUTE', 'K :', 'LOWER COMMAND', 'MAP ITEM :'),
+ 'texts' : ("Each item is associated with a unique numerical id which is returned by the add or clone commands. All commands on items accept those ids as (often first) parameter in order to uniquely identify on which item they should operate. When an id has been allocated to an item, it is never collected even after the item has been destroyed, in a TkZinc session two items cannot have the same id. This property can be quite useful when used in conjonction with tags, which are described below.",
+ "Specifies the form of the joint between the curve segments. This attribute is only applicable if the curve outline relief is flat. The default value is round.",
+ "No TkZinc KeyWord with K initial letter...",
+ "Reorder all the items given by tagOrId so that they will be under the item given by belowThis. If tagOrId name more than one item, their relative order will be preserved. If tagOrId doesn't name an item, an error is raised. If belowThis name more than one item, the bottom most them is used. If belowThis doesn't name an item, an error is raised. If belowThis is omitted the items are put at the bottom most position of their respective groups.",
+ "Map items are typically used for displaying maps on a radar display view. Maps are not be sensitive to mouse or keyboard events, but have been designed to efficiently display large set of points, segments, arcs, and simple texts. A map item is associated to a mapinfo. This mapinfo entity can be either initialized with the videomap command or more generally created and edited with a set of commands described in the The mapinfo related commands section.",
+ ),
+ },
+ 's' : {'numpages' : 8,
+ 'titles' : ('N', 'O', 'P' ,'Q' ,'R' ,'S' ,'T' ,'U'),
+ 'names' : ('NUMPARTS COMMAND :', 'OVERLAP MANAGER :', 'PICKAPERTURE WIDGET OPTION :', 'Q :',
+ 'RENDER WIDGET OPTION :', 'SMOOTH COMMAND', 'TAGS :', 'UNDERLINED ATTRIBUTE :'),
+ 'texts' : ("This command tells how many fieldId are available for event bindings or for field configuration commands in the item specified by tagOrId. If more than one item is named by tagOrId, the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised. This command returns always 0 for items which do not support fields. The command hasfields may be used to decide whether an item has fields.",
+ "his option accepts an item id. It specifies if the label overlapping avoidance algorithm should be allowed to do its work on the track labels and which group should be considered to look for tracks. The default is to enable the avoidance algorithm in the root group (id 1). To disable the algorithm this option should be set to 0.",
+ "Specifies the size of an area around the pointer that is used to tell if the pointer is inside an item. This is useful to lessen the precision required when picking graphical elements. This value must be a positive integer. It defaults to 1.",
+ "No TkZinc KeyWord with Q initial letter...",
+ "Specifies whether to use or not the openGL rendering. When True, requires the GLX extension to the X server. Must be defined at widget creation time. This option is readonly and can be used to ask if the widget is drawing with the GLX extension or in plain X (to adapt the application code for example). The default value is false.",
+ "This command computes a sequence of Bezier segments that will smooth the polygon described by the vertices in coordList and returns a list of lists describing thr points and control points for the generated segments. coordList should be either a flat list of an even number of coordinates in x, y order, or a list of lists of point coordinates X, Y. The returned list can be used to create or change the contour of a curve item.",
+ "Apart from an id, an item can be associated with as many symbolic names as it may be needed by an application. Those names are called tags and can be any string which does not form a valid id (an integer). However the following characters may not be used to form a tag: . * ! ( ) & | :. Tags exists, and may be used in commands, even if no item are associated with them. In contrast an item id doesn't exist if its item is no longer around and thus it is illegal to use it.",
+ "Item Text attribute. If true, a thin line will be drawn under the text characters. The default value is false.",
+ ),
+ },
+ 'w' : {'numpages' : 5,
+ 'titles' : ('V', 'W', 'X', 'Y', 'Z'),
+ 'names' : ('VERTEXAT COMMAND :', 'WAYPOINT ITEM :', 'X11, OpenGL and Windows :', 'Y...', 'ZINC an advanced scriptable Canvas :'),
+ 'texts' : ("Return a list of values describing the vertex and edge closest to the window coordinates x and y in the item described by tagOrId. If tagOrId describes more than one item, the first item in display list order that supports vertex picking is used. The list consists of the index of the contour containing the returned vertices, the index of the closest vertex and the index of a vertex next to the closest vertex that identify the closest edge (located between the two returned vertices).",
+ "Waypoints items have been initially designed for figuring out typical fixed position objects (i.e. beacons or fixes in the ATC vocabulary) with associated block of texts on a radar display for Air Traffic Control. They supports mouse event handling and interactions. However they may certainly be used by other kinds of radar view or even by other kind of plan view with many geographical objects and associated textual information.",
+ "TkZinc was firstly designed for X11 server. Since the 3.2.2 version, TkZinc also offers as a runtime option, the support for openGL rendering, giving access to features such as antialiasing, transparency, color gradients and even a new, openGL oriented, item type : triangles . In order to use the openGL features, you need the support of the GLX extension on your X11 server. We also succeeded in using TkZinc with openGL on the Exceed X11 server (running on windows and developped by Hummingbird) with the 3D extension. ",
+ "No TkZinc KeyWord with Y initial letter...",
+ "TkZinc widgets are very similar to Tk Canvases in that they support structured graphics. But unlike the Canvas, TkZinc can structure the items in a hierarchy, has support for affine 2D transforms, clipping can be set for sub-trees of the item hierarchy, the item set is quite more powerful including field specific items for Air Traffic systems and new rendering techniques such as transparency and gradients. If needed, it is also possible to extend the item set in an additionnal dynamic library through the use of a C api.",
+ ),
+ },
+ }
+
+#----------------------------------------------------------------------- fin de MAIN
+
+def resetTransfo():
+ zinc.raiseitem('move')
+ zinc.treset('move')
+ zinc.treset(curview)
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt CLICK des items tagés 'divider'
+#-----------------------------------------------------------------------------------
+def selectDivider (divname = None , numpage = None):
+ global curview
+ if (divname is None) :
+ tags = zinc.itemcget('current', 'tags')
+ divname = tags[0]
+ numpage = int(tags[2])
+
+ zinc.itemconfigure("(%s && titre)"%(divname), color = '#000099')
+ zinc.itemconfigure("(%s && intercalaire)"%(divname), linewidth = 1.4)
+ zinc.itemconfigure("(%s && page)"%(divname), visible = 0)
+
+ divgroup = zinc.group("(%s && %s)"%(divname, numpage))
+ zinc.raiseitem(divgroup)
+ curview = "(%s && %s && content)"%(divname, numpage)
+ zinc.itemconfigure("(%s && %s && titre)"%(divname, numpage), color = '#000000')
+ zinc.itemconfigure("(%s && %s && intercalaire)"%(divname, numpage), linewidth = 2);
+ zinc.itemconfigure("(%s && %s && page)"%(divname, numpage), visible = 1)
+
+ if (divname == 'div2') :
+ fontname = tabtables[tabanchor]['names'][numpage]
+ explain = tabtables[tabanchor]['texts'][numpage]
+ text = "%s\n\n%s"%(fontname, explain)
+ zinc.itemconfigure("(%s && fontname)"%(divname),
+ text = text)
+ zinc.raiseitem("(%s && fontname)"%(divname))
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt CLICK des items tagés 'selector'
+#-----------------------------------------------------------------------------------
+def clickSelector(btngroup = None , value = None):
+ global tabalign
+ global tabanchor
+ if (btngroup is None and value is None):
+ tags = zinc.itemcget('current', 'tags')
+ btngroup = tags[0]
+ value = tags[1]
+
+ zinc.treset(btngroup)
+ zinc.itemconfigure("(%s && btntext)"%(btngroup), color = '#444444')
+ zinc.itemconfigure("(%s && %s && btntext)"%(btngroup, value) , color = '#2222bb')
+ zinc.translate("(%s && %s)"%(btngroup, value), 0, 1)
+
+ if (value in ('n', 'e', 's', 'w')) :
+ tabanchor = value
+
+ elif (value == 'left' or value == 'center' or value == 'right') :
+ tabalign = value
+
+ tabtable = tabtables[tabanchor]
+ numpages = tabtable['numpages']
+ tabparams = { 'radius' : 8,
+ 'tabwidth' : 72,
+ 'tabheight' : 28,
+ 'numpages' : numpages,
+ 'anchor' : tabanchor,
+ 'alignment' : tabalign,
+ 'overlap' : 3,
+ }
+
+ (shapes, tcoords, inverse) = tabbox_coords(((-240, -160), (240, 100)), **tabparams)
+
+ for index in xrange(7, -1, -1):
+ divgroup = zinc.group("(div2 && %s && intercalaire)"%(index))
+ zinc.itemconfigure(divgroup,
+ visible = (index < numpages))
+
+ if (index >= numpages) :
+ zinc.loweritem(divgroup)
+ else :
+ zinc.raiseitem(divgroup)
+ zinc.itemconfigure("(div2 && %s)"%(index),
+ visible = 1)
+ zinc.coords("(div2 && %s && intercalaire)"%(index),
+ tuple(shapes[index]))
+ if (zinc.type("(div2 && %s && titre)"%(index))) :
+ zinc.coords("(div2 && %s && titre)"%(index), tcoords[index])
+ zinc.itemconfigure("(div2 && %s && titre)"%(index),
+ text = tabtable['titles'][index])
+ selectDivider('div2', 0)
+
+def setBindings():
+ # grab keyboard
+ mw.focus()
+
+ # plus,moins : Zoom++, Zoom--
+ mw.bind('<plus>', lambda ev: viewZoom('up'))
+ mw.bind('<minus>', lambda ev: viewZoom('down'))
+
+ # Up, Down, Right, Left : Translate
+ mw.bind('<KeyPress-Up>', lambda ev: viewTranslate('up'))
+ mw.bind('<KeyPress-Down>', lambda ev: viewTranslate('down'))
+ mw.bind('<KeyPress-Left>', lambda ev: viewTranslate('left'))
+ mw.bind('<KeyPress-Right>', lambda ev: viewTranslate('right'))
+
+
+ # >, < : Rotate counterclockwise et clockwise
+ mw.bind('<greater>', lambda ev: viewRotate('cw'))
+ mw.bind('<less>', lambda ev: viewRotate('ccw'))
+
+ def printMsg(*arg, **kw):
+ for i in arg :
+ print "--> %s : %s"%(i, zinc)
+ for i,j in kw.items():
+ print "%s --> %s"%(i, j)
+
+ # Escape : reset transfos
+ mw.bind('<Escape>', lambda ev, : resetTransfo())
+
+ zinc.bind_tag('divider', '<1>', lambda ev : selectDivider())
+
+ zinc.bind_tag('selector', '<1>', lambda ev : clickSelector())
+
+ zinc.bind_tag('move', '<1>', lambda ev : mobileStart(ev))
+ zinc.bind_tag('move', '<B1-Motion>', lambda ev : mobileMove(ev))
+ zinc.bind_tag('move', '<ButtonRelease>', lambda ev : mobileStop(ev))
+
+ zinc.bind_tag('pushbtn', '<1>', lambda ev : pushButton())
+ zinc.bind_tag('pushbtn', '<ButtonRelease>', lambda ev : pullButton())
+
+ zinc.bind_tag('poly', '<1>', lambda ev : startRotatePolygone(ev))
+ zinc.bind_tag('poly', '<B1-Motion>', lambda ev : rotatePolygone(ev))
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt CLICK des items tagés 'pushbtn'
+#-----------------------------------------------------------------------------------
+def pushButton ():
+ tag = zinc.itemcget('current', 'tags')[0]
+ if (len(zinc.find('withtag', tag)) > 1
+ and not zinc.find('withtag', "(%s && ico)"%(tag))):
+ tag = 'current'
+ zinc.scale(tag, .975, .975)
+ zinc.translate(tag, 1, 1)
+
+ if (zinc.find('withtag', "(%s && ico)"%(tag))) :
+ oldcolor = zinc.itemcget("(%s && ico)"%(tag),
+ 'fillcolor')
+ zinc.itemconfigure('ico',
+ fillcolor = '#000000')
+
+ if (oldcolor == '#000000') :
+ newcolor = '#ffff00'
+ else :
+ newcolor = '#000000'
+ zinc.itemconfigure("(%s && ico)"%(tag),
+ fillcolor = newcolor)
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt RELEASE des items tagés 'pushbtn'
+#-----------------------------------------------------------------------------------
+def pullButton ():
+ tag = zinc.itemcget('current', 'tags')[0]
+ zinc.treset(tag)
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt CATCH des items tagés 'poly'
+# armement de rotation des polygones
+#-----------------------------------------------------------------------------------
+def startRotatePolygone (ev):
+ global previousangle
+ (xref, yref) = zinc.transform(zinc.group('current'), 1, (0, 0))
+ previousangle = line_angle((ev.x, ev.y), (xref, yref))
+
+#-----------------------------------------------------------------------------------
+# Callback sur evt MOTION des items tagés 'poly'
+# rotation des polygones
+#-----------------------------------------------------------------------------------
+def rotatePolygone (ev):
+ global previousangle
+ tag = zinc.itemcget('current', 'tags')[0]
+ (xref, yref) = zinc.transform(zinc.group('current'),
+ 1,
+ (0, 0))
+ newangle = line_angle((ev.x, ev.y),
+ (xref, yref))
+
+ zinc.rotate(tag,
+ math.radians(newangle - previousangle))
+ previousangle = newangle
+
+#-----------------------------------------------------------------------------------
+# Callback CATCH de sélection (début de déplacement) des items tagés 'move'
+#-----------------------------------------------------------------------------------
+def mobileStart (ev):
+ global dx, dy
+ (dx, dy) = (0 - ev.x, 0 - ev.y)
+ zinc.raiseitem('current')
+
+
+
+#-----------------------------------------------------------------------------------
+# Callback MOVE de déplacement des items tagés 'move'
+#-----------------------------------------------------------------------------------
+def mobileMove (ev):
+ global dx, dy
+ zinc.translate('current',
+ ev.x + dx,
+ ev.y +dy)
+ (dx, dy) = (0 - ev.x, 0 - ev.y)
+
+
+#-----------------------------------------------------------------------------------
+# Callback RELEASE de relaché (fin de déplacement) des items tagés 'move'
+#-----------------------------------------------------------------------------------
+def mobileStop (ev):
+ mobileMove(ev)
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evénément Tk <KeyPress> flèche gauche, haut, droite, bas
+# pan (translation) du contenu de la page active (TabBox)
+#-----------------------------------------------------------------------------------
+def viewTranslate (way):
+ if (way == 'left') :
+ dx = -10
+ elif (way == 'right') :
+ dx = 10
+ else :
+ dx = 0
+ if (way == 'up') :
+ dy = -10
+ elif (way == 'down') :
+ dy = 10
+ else:
+ dy = 0
+
+ zinc.translate(curview, dx, dy);
+
+#-----------------------------------------------------------------------------------
+# Callback sur evénément Tk <KeyPress> "+" ou "-"
+# zoom du contenu de la page active (TabBox)
+#-----------------------------------------------------------------------------------
+def viewZoom (key) :
+ global curview
+ if (key == 'up') :
+ scaleratio = 1 + zoomfactor
+ else :
+ scaleratio = 1 - zoomfactor
+
+ zinc.scale(curview, scaleratio, scaleratio);
+
+
+
+#-----------------------------------------------------------------------------------
+# Callback sur evénément Tk <KeyPress> ">" ou "<"
+# rotation du contenu de la page active (TabBox)
+#-----------------------------------------------------------------------------------
+def viewRotate (way) :
+ delta_angle = rotate_angle
+ if (way == 'cw') :
+ delta_angle *= -1
+
+ zinc.rotate(curview, delta_angle)
+
+
+# creation de la fenetre principale
+mw = Tkinter.Tk()
+mw.geometry("700x560+0+0")
+mw.title('Test Graphics Module')
+
+
+# creation du widget Zinc
+zinc = Zinc.Zinc(render = 1,
+ width = 700,
+ height = 560,
+ borderwidth = 0,
+ lightangle = 140,
+ backcolor = '#cccccc',)
+zinc.pack(fill = 'both', expand = 1)
+
+
+# initialise les gradients nommés
+pictorial.set_gradients(zinc, **gradset)
+
+# création de la vue principale
+tgroup = zinc.add('group', 1)
+zinc.coords(tgroup, (350, 240))
+
+# consigne globale
+zinc.add('text', 1,
+ position = (50, 470),
+ text = "Global interations :\n<Up>, <Down>, <Left> and <Right> keys move content of TabBox pages\n<Plus> and <Minus> keys zoom out and zoom in this page\n<Greater> and <Less> keys rotate this page\n<Escape> key reset transfos",
+ font = font_9b,
+ color = '#555555',
+ spacing = 2,
+ )
+
+# Création des pages d'exemples
+(shapes, tcoords, inverse) = tabbox_coords(((-315, -210), (315, 210)),
+ numpages = 7,
+ overlap = 2,
+ radius = 8,
+ tabheight = 26,
+ tabwidth = [92, 100 ,82 ,82 ,82 ,120 , 80],
+ )
+
+# to find some images (used as textures) needed by this demo
+texture = pictorial.get_image(zinc, 'paper.gif')
+# création des items zinc correspondants
+i = len(shapes) - 1
+pagenames = ['Rectangle', 'Hippodrome', 'Polygone', 'Polyline', 'PathLine', 'MultiContours', 'TabBox']
+pagegroups=[]
+
+lshapes=list(shapes)
+lshapes.reverse()
+currentcoords=coords2lpts(tcoords)
+for shape in lshapes:
+ divgroup = zinc.add('group', tgroup)
+
+ # création de l'intercalaire
+ divider = zinc.add('curve',
+ divgroup,
+ lpts2coords(shape),
+ closed = 1,
+ priority = 10,
+ linewidth = 1,
+ linecolor = '#000000',
+ filled = 1,
+ tile = texture,
+ tags = ('div1', 'divider', i, 'intercalaire'),
+ )
+
+ # groupe page clippé
+ page = zinc.add('group',
+ divgroup,
+ priority = 100,
+ tags = ('div1', i, 'page'),
+ )
+ clip = zinc.add('rectangle',
+ page,
+ ((-300, -170), (300, 195)),
+ linewidth = 1,
+ linecolor = '#000099',
+ filled = 1,
+ fillcolor = '#000000;4',
+ )
+ zinc.itemconfigure(page, clip = clip)
+
+ pgroup = zinc.add('group', page,
+ tags = ('div1', i, 'content'),
+ )
+
+ pagegroups.append(pgroup)
+
+ currentcoords[i][1] -= 6
+
+
+ # titre de l'intercalaire
+ zinc.add('text',
+ divgroup,
+ position = tuple(currentcoords[i]),
+ text = pagenames[i],
+ font = font_9b,
+ alignment = 'center',
+ anchor = 'n',
+ color = '#000099',
+ priority = 200,
+ tags = ('div1', 'divider', i, 'titre'),
+ )
+ i-= 1
+
+
+# création du contenu des pages
+i = 0
+pagenames.reverse()
+for pagename in pagenames:
+ if ( pagesconf.has_key(pagename)) :
+ pagestyle = pagesconf[pagename]
+ pgroup = pagegroups[i]
+ for ( itemname, itemstyle) in pagestyle.items() :
+ if (itemname == 'consigne') :
+ group = zinc.group(pgroup)
+ else:
+ group = pgroup
+ itemstyle['name'] = itemname
+ build_zinc_item(zinc, group, **itemstyle)
+
+ i+=1
+
+
+
+# initialisation de la TabBox
+clickSelector('sel1', 'n')
+clickSelector('sel2', 'left')
+selectDivider('div1', 0)
+
+# initialisation des bindings
+setBindings()
+
+
+mw.mainloop()
+
+
+#Local Variables:
+#mode : python
+#tab'width' : 4
+#end:
+