|
1 ### -*- coding: utf-8 -*- #################################################### |
|
2 ############################################################################## |
|
3 # |
|
4 # Copyright (c) 2012 Thierry Florac <tflorac AT ulthar.net> |
|
5 # All Rights Reserved. |
|
6 # |
|
7 # This software is subject to the provisions of the Zope Public License, |
|
8 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
9 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
10 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
11 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
12 # FOR A PARTICULAR PURPOSE. |
|
13 # |
|
14 ############################################################################## |
|
15 |
|
16 |
|
17 # import standard packages |
|
18 import decimal |
|
19 import string |
|
20 |
|
21 # import Zope3 interfaces |
|
22 from z3c.form.interfaces import IWidget |
|
23 from zope.schema.interfaces import ITextLine, IDecimal |
|
24 |
|
25 # import local interfaces |
|
26 |
|
27 # import Zope3 packages |
|
28 from z3c.form.converter import BaseDataConverter, FormatterValidationError |
|
29 from zope.component import adapts |
|
30 from zope.interface import implements |
|
31 from zope.schema import TextLine, Decimal |
|
32 from zope.schema._bootstrapfields import InvalidValue |
|
33 |
|
34 # import local packages |
|
35 |
|
36 from ztfy.utils import _ |
|
37 |
|
38 |
|
39 class StringLine(TextLine): |
|
40 """String line field""" |
|
41 |
|
42 _type = str |
|
43 |
|
44 def fromUnicode(self, value): |
|
45 return str(value) |
|
46 |
|
47 |
|
48 # |
|
49 # Color field |
|
50 # |
|
51 |
|
52 class IColorField(ITextLine): |
|
53 """Marker interface for color fields""" |
|
54 |
|
55 |
|
56 class ColorField(TextLine): |
|
57 """Color field""" |
|
58 |
|
59 implements(IColorField) |
|
60 |
|
61 def __init__(self, *args, **kw): |
|
62 super(ColorField, self).__init__(max_length=6, *args, **kw) |
|
63 |
|
64 def _validate(self, value): |
|
65 if len(value) not in (3, 6): |
|
66 raise InvalidValue, _("Color length must be 3 or 6 characters") |
|
67 for v in value: |
|
68 if v not in string.hexdigits: |
|
69 raise InvalidValue, _("Color value must contain only valid color codes (numbers or letters between 'A' end 'F')") |
|
70 super(ColorField, self)._validate(value) |
|
71 |
|
72 |
|
73 # |
|
74 # Pointed decimal field |
|
75 # |
|
76 |
|
77 class IDottedDecimalField(IDecimal): |
|
78 """Marker interface for dotted decimal fields""" |
|
79 |
|
80 |
|
81 class DottedDecimalField(Decimal): |
|
82 """Dotted decimal field""" |
|
83 |
|
84 implements(IDottedDecimalField) |
|
85 |
|
86 |
|
87 class DottedDecimalDataConverter(BaseDataConverter): |
|
88 """Dotted decimal field data converter""" |
|
89 |
|
90 adapts(IDottedDecimalField, IWidget) |
|
91 |
|
92 errorMessage = _('The entered value is not a valid decimal literal.') |
|
93 |
|
94 def __init__(self, field, widget): |
|
95 super(DottedDecimalDataConverter, self).__init__(field, widget) |
|
96 |
|
97 def toWidgetValue(self, value): |
|
98 if not value: |
|
99 return self.field.missing_value |
|
100 return str(value) |
|
101 |
|
102 def toFieldValue(self, value): |
|
103 if value is self.field.missing_value: |
|
104 return u'' |
|
105 if not value: |
|
106 return None |
|
107 try: |
|
108 return decimal.Decimal(value) |
|
109 except decimal.InvalidOperation: |
|
110 raise FormatterValidationError(self.errorMessage, value) |