13
13
# Union, TraitError, HasTraits,
14
14
# NoDefaultSpecified, TraitType)
15
15
import numpy as np
16
+ import re
16
17
17
18
# override for backward compatability
18
19
class Configurable (Configurable ): pass
@@ -84,6 +85,7 @@ class Color(TraitType):
84
85
info_text = 'float, int, tuple of float or int, or a hex string color'
85
86
default_value = (0.0 ,0.0 ,0.0 ,0.0 )
86
87
named_colors = {}
88
+ _is_hex16 = re .compile (r'#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?$' )
87
89
88
90
def _int_to_float (self , value ):
89
91
as_float = (np .array (value )/ 255 ).tolist ()
@@ -99,18 +101,13 @@ def _int_to_hex(self, value):
99
101
return as_hex
100
102
101
103
def _hex_to_float (self , value ):
102
- # Expects #FFFFFF format
103
- split_hex = (value [1 :3 ],value [3 :5 ],value [5 :7 ])
104
- as_float = (np .array ([int (v ,16 ) for v in split_hex ])/ 255.0 ).tolist ()
104
+ if len (value ) == 7 :
105
+ split_hex = (value [1 :3 ],value [3 :5 ],value [5 :7 ])
106
+ as_float = (np .array ([int (v ,16 ) for v in split_hex ])/ 255.0 ).tolist ()
107
+ elif len (value ) == 4 :
108
+ as_float = (np .array ([int (v + v ,16 ) for v in value [1 :]])/ 255.0 ).tolist ()
105
109
return as_float
106
110
107
- def _is_hex16 (self , value ):
108
- try :
109
- int (value , 16 )
110
- return True
111
- except :
112
- return False
113
-
114
111
def _float_to_shade (self , value ):
115
112
grade = value * 255.0
116
113
return (grade ,grade ,grade )
@@ -121,21 +118,28 @@ def _int_to_shade(self, value):
121
118
122
119
def validate (self , obj , value ):
123
120
in_range = False
124
- if value is None or value is False or value in ['none' ,'' ]:
125
- # Return transparent if no other default alpha was set
126
- return (0.0 , 0.0 , 0.0 , 1.0 )
121
+ if value is True :
122
+ self .error (obj , value )
127
123
128
- if isinstance (value , float ) and 0 <= value <= 1 :
129
- value = self ._float_to_shade (value )
130
- else :
131
- in_range = False
124
+ elif value is None or value is False or value in ['none' ,'' ]:
125
+ value = (0.0 , 0.0 , 0.0 , 1.0 )
126
+ in_range = True
132
127
133
- if isinstance (value , int ) and 0 <= value <= 255 :
134
- value = self ._int_to_shade (value )
135
- else :
136
- in_range = False
128
+ elif isinstance (value , float ):
129
+ if 0 <= value <= 1 :
130
+ value = self ._float_to_shade (value )
131
+ in_range = True
132
+ else :
133
+ in_range = False
137
134
138
- if isinstance (value , (tuple , list )) and len (value ) in (3 ,4 ):
135
+ elif isinstance (value , int ):
136
+ if 0 <= value <= 255 :
137
+ value = self ._int_to_shade (value )
138
+ in_range = True
139
+ else :
140
+ in_range = False
141
+
142
+ elif isinstance (value , (tuple , list )) and len (value ) in (3 ,4 ):
139
143
is_all_float = np .prod ([isinstance (v , (float )) for v in value ])
140
144
in_range = np .prod ([(0 <= v <= 1 ) for v in value ])
141
145
if is_all_float and in_range :
@@ -146,10 +150,8 @@ def validate(self, obj, value):
146
150
if is_all_int and in_range :
147
151
value = self ._int_to_float (value )
148
152
149
- if isinstance (value , str ) and len (value ) == 7 and value [0 ] == '#' :
150
- is_all_hex16 = np .prod ([self ._is_hex16 (v ) for v in \
151
- (value [1 :3 ],value [3 :5 ],value [5 :7 ])])
152
- if is_all_hex16 :
153
+ elif isinstance (value , str ) and len (value ) in [4 ,7 ] and value [0 ] == '#' :
154
+ if self ._is_hex16 .match (value ):
153
155
value = self ._hex_to_float (value )
154
156
in_range = np .prod ([(0 <= v <= 1 ) for v in value ])
155
157
if in_range :
@@ -158,7 +160,7 @@ def validate(self, obj, value):
158
160
elif isinstance (value , str ) and value in self .named_colors :
159
161
value = self .validate (obj , self .named_colors [value ])
160
162
in_range = True
161
-
163
+
162
164
if in_range :
163
165
if self ._metadata ['as_hex' ]:
164
166
return self ._float_to_hex (value )
0 commit comments