Package libxyz :: Package ui :: Module colors
[hide private]
[frames] | no frames]

Source Code for Module libxyz.ui.colors

  1  #-*- coding: utf8 -* 
  2  # 
  3  # Max E. Kuznecov ~syhpoon <syhpoon@syhpoon.name> 2008 
  4  # 
  5  # This file is part of XYZCommander. 
  6  # XYZCommander is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # XYZCommander is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 13  # GNU Lesser Public License for more details. 
 14  # You should have received a copy of the GNU Lesser Public License 
 15  # along with XYZCommander. If not, see <http://www.gnu.org/licenses/>. 
 16   
 17  import copy 
 18  import re 
 19   
 20  from libxyz import const 
 21  from libxyz.exceptions import XYZValueError 
 22  from libxyz.ui.display import is_lowui_ge_0_9_9 
23 24 -class Color(object):
25 """ 26 Base color 27 """ 28 29 colors = {} 30 ctype = u"base" 31
32 - def __init__(self, color):
33 if not self.is_color_valid(color): 34 raise XYZValueError(_(u"Invalid %s color: %s" % \ 35 (self.ctype, str(color)))) 36 37 self.color = None 38 self._set_color(color)
39 40 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41
42 - def is_color_valid(self, color):
43 """ 44 Check if color is valid 45 """ 46 47 return color in self.colors
48 49 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 50
51 - def _set_color(self, color):
52 self.color = self.colors[color]
53 54 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55
56 - def __str__(self):
57 return u"<%s color: %s>" % (self.ctype, str(self.color))
58 59 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60
61 - def __repr__(self):
62 return self.__str__()
63
64 #++++++++++++++++++++++++++++++++++++++++++++++++ 65 66 -class Foreground(Color):
67 """ 68 Foreground color 69 """ 70 71 colors = { 72 u"BLACK": u"black", 73 u"BROWN": u"brown", 74 u"YELLOW": u"yellow", 75 u"WHITE": u"white", 76 u"DEFAULT": u"default", 77 78 u"DARK_BLUE": u"dark blue", 79 u"DARK_MAGENTA": u"dark magenta", 80 u"DARK_CYAN": u"dark cyan", 81 u"DARK_RED": u"dark red", 82 u"DARK_GREEN": u"dark green", 83 u"DARK_GRAY": u"dark gray", 84 85 u"LIGHT_GRAY": u"light gray", 86 u"LIGHT_RED": u"light red", 87 u"LIGHT_GREEN": u"light green", 88 u"LIGHT_BLUE": u"light blue", 89 u"LIGHT_MAGENTA": u"light magenta", 90 u"LIGHT_CYAN": u"light cyan", 91 } 92 93 ctype = u"foreground"
94
95 #++++++++++++++++++++++++++++++++++++++++++++++++ 96 97 -class Background(Color):
98 """ 99 Background color 100 """ 101 102 colors = { 103 u"BLACK": u"black", 104 u"BROWN": u"brown", 105 u"DEFAULT": u"default", 106 107 u"DARK_RED": u"dark red", 108 u"DARK_GREEN": u"dark green", 109 u"DARK_BLUE": u"dark blue", 110 u"DARK_MAGENTA": u"dark magenta", 111 u"DARK_CYAN": u"dark cyan", 112 113 u"LIGHT_GRAY": u"light gray", 114 } 115 116 ctype = u"background"
117
118 #++++++++++++++++++++++++++++++++++++++++++++++++ 119 120 -class Attribute(Color):
121 """ 122 Terminal attributes 123 """ 124 125 colors = { 126 u"BOLD": u"bold", 127 u"UNDERLINE": u"underline", 128 u"BLINK": u"blink", 129 u"STANDOUT": u"standout", 130 } 131 132 ctype = u"attribute"
133
134 #++++++++++++++++++++++++++++++++++++++++++++++++ 135 136 -class BaseHighColor(Color):
137 """ 138 High color can contain value of form: 139 140 #009 (0% red, 0% green, 60% red, like HTML colors) 141 #fcc (100% red, 80% green, 80% blue) 142 g40 (40% gray, decimal), 'g#cc' (80% gray, hex), 143 #000, 'g0', 'g#00' (black), 144 #fff, 'g100', 'g#ff' (white) 145 h8 (color number 8), 'h255' (color number 255) 146 """ 147
148 - def is_color_valid(self, color):
149 # Regular color is also valid 150 if color in self.colors: 151 return True 152 153 # Else check for high color 154 hexre = r"(?:\d|[a-fA-F])" 155 hicolorre = re.compile(r"^((?:#%(hexre)s{3})|(?:g\d{1,3})|"\ 156 r"(?:g#%(hexre)s{1,2})|(?:h\d{1,3}))$" % 157 locals()) 158 159 if hicolorre.match(color) is None: 160 return False 161 else: 162 return True
163 164 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 165
166 - def _set_color(self, color):
167 if color in self.colors: 168 self.color = self.colors[color] 169 else: 170 self.color = color
171
172 #++++++++++++++++++++++++++++++++++++++++++++++++ 173 174 -class ForegroundHigh(BaseHighColor):
175 colors = Foreground.colors
176
177 #++++++++++++++++++++++++++++++++++++++++++++++++ 178 179 -class BackgroundHigh(BaseHighColor):
180 colors = Background.colors
181
182 #++++++++++++++++++++++++++++++++++++++++++++++++ 183 184 -class Palette(object):
185 """ 186 Palette abstraction 187 """ 188 189 @classmethod
190 - def convert(cls, config):
191 """ 192 Convert config text colors to tuple of instances 193 """ 194 195 fg = config.get("foreground", None) 196 197 if fg is not None: 198 fg = Foreground(fg) 199 200 bg = config.get("background", None) 201 202 if bg is not None: 203 bg = Background(bg) 204 205 fg_attrs = [Attribute(x) for x in 206 config.get("fg_attributes", [])] or None 207 208 mono = [Attribute(x) for x in config.get("mono", [])] or None 209 210 fg_high = config.get("foreground_high", None) 211 212 if fg_high is not None: 213 fg_high = ForegroundHigh(fg_high) 214 215 bg_high = config.get("background_high", None) 216 217 if bg_high is not None: 218 bg_high = BackgroundHigh(bg_high) 219 220 return (fg, bg, fg_attrs, mono, fg_high, bg_high)
221 222 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 223
224 - def __init__(self, name, fg, bg, fg_attrs=None, mono=None, 225 fg_high=None, bg_high=None):
226 """ 227 Init palette. 228 229 @param name: Palette name 230 """ 231 232 self.name = name 233 234 self._fg = None 235 self._bg = None 236 self._fg_attrs = None 237 self._mono = None 238 self._fg_high = None 239 self._bg_high = None 240 241 self.fg = fg 242 self.bg = bg 243 self.fg_attrs = fg_attrs 244 self.mono = mono 245 self.fg_high = fg_high 246 self.bg_high = bg_high
247 248 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 249
250 - def _fg_get(self):
251 return self._fg
252
253 - def _fg_set(self, fg):
254 if fg is not None and not isinstance(fg, Foreground): 255 raise XYZValueError(_(u"Invalid argument type %s, "\ 256 u"libxyz.ui.color.Foreground instance "\ 257 u"expected." % type(fg))) 258 else: 259 self._fg = fg
260 261 fg = property(_fg_get, _fg_set) 262 263 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 264
265 - def _bg_get(self):
266 return self._bg
267
268 - def _bg_set(self, bg):
269 if bg is not None and not isinstance(bg, Background): 270 raise XYZValueError(_(u"Invalid argument type %s, "\ 271 u"libxyz.ui.color.Background or instance "\ 272 u"expected." % type(bg))) 273 274 self._bg = bg
275 276 bg = property(_bg_get, _bg_set) 277 278 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 279
280 - def _fg_attrs_get(self):
281 return self._fg_attrs
282
283 - def _fg_attrs_set(self, attrs):
284 if attrs is not None: 285 for attr in attrs: 286 if not isinstance(attr, Attribute): 287 raise XYZValueError(_(u"Invalid argument type %s, "\ 288 u"libxyz.ui.color.Attribute "\ 289 u"instance expected." % type(attr))) 290 291 self._fg_attrs = attrs
292 293 fg_attrs = property(_fg_attrs_get, _fg_attrs_set) 294 295 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 296
297 - def _mono_get(self):
298 return self._mono
299
300 - def _mono_set(self, mono):
301 if mono is not None: 302 for attr in mono: 303 if not isinstance(attr, Attribute): 304 raise XYZValueError(_(u"Invalid argument type %s, "\ 305 u"libxyz.ui.color.Attribute "\ 306 u"instance expected." % type(mono))) 307 308 self._mono = mono
309 310 mono = property(_mono_get, _mono_set) 311 312 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 313
314 - def _fg_high_get(self):
315 return self._fg_high
316
317 - def _fg_high_set(self, fg_high):
318 if fg_high is not None and not isinstance(fg_high, ForegroundHigh): 319 raise XYZValueError(_(u"Invalid argument type %s, "\ 320 u"libxyz.ui.color.ForegroundHigh instance "\ 321 u"expected." % type(fg_high))) 322 else: 323 self._fg_high = fg_high
324 325 fg_high = property(_fg_high_get, _fg_high_set) 326 327 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 328
329 - def _bg_high_get(self):
330 return self._bg_high
331
332 - def _bg_high_set(self, bg_high):
333 if bg_high is not None and not isinstance(bg_high, BackgroundHigh): 334 raise XYZValueError(_(u"Invalid argument type %s, "\ 335 u"libxyz.ui.color.BackgroundHigh instance "\ 336 u"expected." % type(bg_high))) 337 else: 338 self._bg_high = bg_high
339 340 bg_high = property(_bg_high_get, _bg_high_set) 341 342 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 343
344 - def get_palette(self, display=const.DEFAULT_DISPLAY_DRIVER):
345 """ 346 Return urwid-compatible palette tuple 347 """ 348 349 raw = display == "raw" 350 351 fg = self.fg.color 352 fg_attrs = self.fg_attrs 353 354 # Append attributes to foreground color 355 if fg_attrs is not None and is_lowui_ge_0_9_9() and raw: 356 fg = ",".join([fg] + [x.color for x in fg_attrs]) 357 358 bg = self.bg.color 359 mono = self.mono 360 361 if mono is not None: 362 mono = ",".join([x.color for x in mono]) 363 364 fg_high = self.fg_high 365 366 if fg_high is not None: 367 fg_high = fg_high.color 368 369 if fg_attrs is not None and is_lowui_ge_0_9_9() and raw: 370 fg_high = ",".join([fg_high] + [x.color for x in fg_attrs]) 371 372 bg_high = self.bg_high 373 374 if bg_high is not None: 375 bg_high = bg_high.color 376 377 result = (self.name, fg, bg, mono) 378 379 if is_lowui_ge_0_9_9() and raw: 380 result += (fg_high, bg_high) 381 382 return result
383 384 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 385
386 - def set_fg(self, fg):
387 """ 388 Set foreground color 389 """ 390 391 self.fg = fg
392 393 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 394
395 - def set_bg(self, bg):
396 """ 397 Set background color 398 """ 399 400 self.bg = bg
401 402 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 403
404 - def copy(self):
405 """ 406 Return copy of Palette instance 407 """ 408 409 return copy.deepcopy(self)
410 411 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 412
413 - def __call__(self, config):
414 new = self.copy() 415 416 fg, bg, fg_attrs, mono, fg_high, bg_high = self.convert(config) 417 418 if fg: 419 new.fg = fg 420 if bg: 421 new.bg = bg 422 if fg_attrs: 423 new.fg_attrs = fg_attrs 424 if mono: 425 new.mono = mono 426 if fg_high: 427 new.fg_high = fg_high 428 if bg_high: 429 new.bg_high = bg_high 430 431 return new
432