##############################################################################
# ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
#
# Copyright (c) 2001-2009 Thanasis Stamos, August 23, 2009
# URL: http://thancad.sourceforge.net
# e-mail: cyberthanasis@excite.com
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details (www.gnu.org/licenses/gpl.html).
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
"""\
ThanCad 0.0.9 "DoesSomething": 2dimensional CAD with raster support for engineers.
This module defines the classes for layer attributes.
"""
import p_ggen, p_gimdxf
############################################################################
############################################################################
class ThanAtt:
"""A standard attribute of a ThanLayer, such as monitor color.
thanVal : The value of the attribute, either personal or inherited py its parent.
thanAct : The value of the attribute as it is already drawn on the screen (Tkinter canvas).
Almost always it is equal to thanVal.
thanInher: True if the attribute's value is inherited by its parent.
thanPers : The value that the user set to this attribute. When thanInher is False
thanVal is equal to thanPers.
EXPLANATION
From now on the "moncolor" is used as an example of an attribute.
When a layer is created the thanInher is set to true, and thanVal, thanPers
attributes are set to the "moncolor" of the parent, and thanAct is set
to None (since nothing is drawn on the screen with this attribute yet).
If the user changes the "moncolor" to "red", thanInher is set to False,
thanVal and thanPers is set to the color chosen by the user, and thanAct
is not altered. (a) When the user presses OK, ThanCad looks at the children
of current current layer and if thanInher of "moncolor" is True, it sets
the corresponding thanVal to "red". Then it does the same for the children's
children and so on.
Then it checks all the (leaf) layers to see if the thanAct of "moncolor"
is different to thanVal. If it is different, it changes the "moncolor"
of all the elements that belong to this layer (and which are already drawn
on the screen; if no elements of the layer are drawn on the screen, or if
the layer is "off" nothing happens).
If the user changes the "moncolor" to the "<BYPARENT>" value, thanInher
is set to True, thanVal is set to thanVal of the parent layer's thanVal,
and thanPers and thanAct are not altered. Then as (a) above.
If the user changes the "moncolor" to the "<PERSONAL>" value, thanInher
is set to False, thanVal is set to thanPers, and thanPers and thanAct are
not altered. Then as (a) above.
When the elements of a layer are drawn on the screen (Tkinter Canvas)
thanAct is set to thanVal.
"""
def __init__(self, val, inherit=True):
self.thanVal = val
self.thanAct = None # If it is not explicitely set later, there will be a failure
self.thanPers = val
self.thanInher = inherit
def thanValSet(self, val):
"It is useful only for override."
self.thanVal = val
# def thanCloneR(self):
# "Clones current attribute; inheritance from self is forced."
# att = self.__class__(self, self.thanVal)
# att.__dict__.update(self.__dict__)
# return att
def __str__(self): return p_ggen.thanUnunicode(self.thanVal)
############################################################################
############################################################################
class ThanAttOnoffInherit(ThanAtt):
"An attribute that takes False or True values and it can inherit."
def __init__(self, val, inherit=True, on="ON", off="off"):
self.thanOn = on; self.thanOff = off
ThanAtt.__init__(self, self.tobool(val), inherit)
def thanValSet(self, val):
"Save the value as boolean."
self.thanVal = self.tobool(val)
def tobool(self, val):
"Makes the value boolean."
try: val = val.strip()+ "" # If it is a string, strip white chars
except: string = False
else: string = True
if string:
if val == self.thanOn.strip(): val = True
else: val = False
else:
if val: val = True
else: val = False
return val
def __str__(self):
if self.thanVal: return self.thanOn
else: return self.thanOff
class ThanAttOnoff(ThanAttOnoffInherit):
"An attribute that takes False or True values but can't inherit."
def __init__(self, val, inherit=False, on=" x ", off=" _ "):
assert not inherit, "Forced inheritance attributes can not be inherited manually."
ThanAttOnoffInherit.__init__(self, val, inherit, on, off)
############################################################################
############################################################################
class ThanAttTstyle(ThanAtt):
"An attribute that takes False or True values."
def __init__(self, val, *args, **kw):
ThanAtt.__init__(self, str(val), *args, **kw)
def thanValSet(self, val):
"It is useful only for override."
self.thanVal = str(val)
############################################################################
############################################################################
class ThanAttCol(ThanAtt):
"""ThanCad color class.
A ThanCad colour is a type of 3 integer (r, g, b) eahc of which
has values 0 <= r,g,b <= 255
r=red, g=green, b=blue
"""
def __init__(self, col, inherit=True):
self.thanValSet(col)
ThanAtt.__init__(self, self.thanVal, inherit) # Initialise Base class
def thanValSet(self, val):
"""Tranforms val to ThanCol object; raises ValueError for invalid colors.
val may be one of the following:
1. ThanCol instance
2. A string which contains the name of the color (e.g. "yellow")
3. A string which contains 1 integer which is the index of the color in the
partial list (e.g. "2")
4. A string which contains 3 integers, separated by spaces, which represent
the rgb value of the color (e.g. "10 50 200")
5. A list/tuple/sequence of 3 texts or 3 integers, which represent the rgb
value of the color (e.g. ["10","50","200"])
"""
col = val
terr = "Invalid ThanCad color: %s" % (col,)
if isinstance(col, ThanAttCol): self.__dict__.update(col.__dict__); return
try: col + "" # Is it string?
except: string = False
else: string = True
if string:
cs = col.split()
else:
try: cs = col[0], col[1], col[2]; n = len(cs)
except: raise ValueError, terr
if n != 3: raise ValueError, terr
if len(cs) == 1:
col = cs[0]
try: rgb = p_gimdxf.thanDxfColName2Rgb.get(col, None) or p_gimdxf.thanDxfColCode2Rgb.get(int(col), None)
except ValueError: raise ValueError, terr
if not rgb: raise ValueError, terr
elif len(cs) != 3:
raise ValueError, terr
else:
try: rgb = tuple(map(int, cs))
except ValueError: raise ValueError, terr
for i in rgb:
if i < 0 or i > 255: raise ValueError, terr
self.thanVal = rgb
self.thanPartial = p_gimdxf.thanRgb2DxfColCode.get(rgb, None)
self.thanName = p_gimdxf.thanRgb2DxfColName.get(rgb, None)
self.thanTk = p_gimdxf.thanFormTkcol % rgb
self.thanNorm = str(self.thanName or self.thanPartial or ("%d %d %d" % rgb))
def __str__(self): return self.thanNorm
def rgbShow(self):
"Shows rgb if normal is partial or name."
if self.thanName or self.thanPartial: return "RGB: %d %d %d" % self.thanVal
else: return ""
def thanDxf(self):
"Returns a dxf color that resembles self's color."
return p_gimdxf.thanRgb2DxfColCodeApprox(self.thanVal)
def than2Gray(self):
"Transform the colour to gray scale accroding to ITU-R 601-2 transform; return an integer."
return p_gimdxf.thanRgb2Gray(self.thanVal)
def thanAttCol(col):
"Factory function for ThanCol class which does not stop in case of mistake."
try: return ThanAttCol(col)
except ValueError: return None
|