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 u"DARK_GRAY": u"dark gray" 115 } 116 117 ctype = u"background"
118
119 #++++++++++++++++++++++++++++++++++++++++++++++++ 120 121 -class Attribute(Color):
122 """ 123 Terminal attributes 124 """ 125 126 colors = { 127 u"BOLD": u"bold", 128 u"UNDERLINE": u"underline", 129 u"BLINK": u"blink", 130 u"STANDOUT": u"standout", 131 } 132 133 ctype = u"attribute"
134
135 #++++++++++++++++++++++++++++++++++++++++++++++++ 136 137 -class BaseHighColor(Color):
138 """ 139 High color can contain value of form: 140 141 #009 (0% red, 0% green, 60% red, like HTML colors) 142 #fcc (100% red, 80% green, 80% blue) 143 g40 (40% gray, decimal), 'g#cc' (80% gray, hex), 144 #000, 'g0', 'g#00' (black), 145 #fff, 'g100', 'g#ff' (white) 146 h8 (color number 8), 'h255' (color number 255) 147 """ 148
149 - def is_color_valid(self, color):
150 # Regular color is also valid 151 if color in self.colors: 152 return True 153 154 # Else check for high color 155 hexre = r"(?:\d|[a-fA-F])" 156 hicolorre = re.compile(r"^((?:#%(hexre)s{3})|(?:g\d{1,3})|"\ 157 r"(?:g#%(hexre)s{1,2})|(?:h\d{1,3}))$" % 158 locals()) 159 160 if hicolorre.match(color) is None: 161 return False 162 else: 163 return True
164 165 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 166
167 - def _set_color(self, color):
168 if color in self.colors: 169 self.color = self.colors[color] 170 else: 171 self.color = color
172
173 #++++++++++++++++++++++++++++++++++++++++++++++++ 174 175 -class ForegroundHigh(BaseHighColor):
176 colors = Foreground.colors
177
178 #++++++++++++++++++++++++++++++++++++++++++++++++ 179 180 -class BackgroundHigh(BaseHighColor):
181 colors = Background.colors
182
183 #++++++++++++++++++++++++++++++++++++++++++++++++ 184 185 -class Palette(object):
186 """ 187 Palette abstraction 188 """ 189 190 @classmethod
191 - def convert(cls, config):
192 """ 193 Convert config text colors to tuple of instances 194 """ 195 196 fg = config.get("foreground", None) 197 198 if fg is not None: 199 fg = Foreground(fg) 200 201 bg = config.get("background", None) 202 203 if bg is not None: 204 bg = Background(bg) 205 206 fg_attrs = [Attribute(x) for x in 207 config.get("fg_attributes", [])] or None 208 209 mono = [Attribute(x) for x in config.get("mono", [])] or None 210 211 fg_high = config.get("foreground_high", None) 212 213 if fg_high is not None: 214 fg_high = ForegroundHigh(fg_high) 215 216 bg_high = config.get("background_high", None) 217 218 if bg_high is not None: 219 bg_high = BackgroundHigh(bg_high) 220 221 return (fg, bg, fg_attrs, mono, fg_high, bg_high)
222 223 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 224
225 - def __init__(self, name, fg, bg, fg_attrs=None, mono=None, 226 fg_high=None, bg_high=None):
227 """ 228 Init palette. 229 230 @param name: Palette name 231 """ 232 233 self.name = name 234 235 self._fg = None 236 self._bg = None 237 self._fg_attrs = None 238 self._mono = None 239 self._fg_high = None 240 self._bg_high = None 241 242 self.fg = fg 243 self.bg = bg 244 self.fg_attrs = fg_attrs 245 self.mono = mono 246 self.fg_high = fg_high 247 self.bg_high = bg_high
248 249 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 250
251 - def _fg_get(self):
252 return self._fg
253
254 - def _fg_set(self, fg):
255 if fg is not None and not isinstance(fg, Foreground): 256 raise XYZValueError(_(u"Invalid argument type %s, "\ 257 u"libxyz.ui.color.Foreground instance "\ 258 u"expected." % type(fg))) 259 else: 260 self._fg = fg
261 262 fg = property(_fg_get, _fg_set) 263 264 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 265
266 - def _bg_get(self):
267 return self._bg
268
269 - def _bg_set(self, bg):
270 if bg is not None and not isinstance(bg, Background): 271 raise XYZValueError(_(u"Invalid argument type %s, "\ 272 u"libxyz.ui.color.Background or instance "\ 273 u"expected." % type(bg))) 274 275 self._bg = bg
276 277 bg = property(_bg_get, _bg_set) 278 279 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 280
281 - def _fg_attrs_get(self):
282 return self._fg_attrs
283
284 - def _fg_attrs_set(self, attrs):
285 if attrs is not None: 286 for attr in attrs: 287 if not isinstance(attr, Attribute): 288 raise XYZValueError(_(u"Invalid argument type %s, "\ 289 u"libxyz.ui.color.Attribute "\ 290 u"instance expected." % type(attr))) 291 292 self._fg_attrs = attrs
293 294 fg_attrs = property(_fg_attrs_get, _fg_attrs_set) 295 296 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 297
298 - def _mono_get(self):
299 return self._mono
300
301 - def _mono_set(self, mono):
302 if mono is not None: 303 for attr in mono: 304 if not isinstance(attr, Attribute): 305 raise XYZValueError(_(u"Invalid argument type %s, "\ 306 u"libxyz.ui.color.Attribute "\ 307 u"instance expected." % type(mono))) 308 309 self._mono = mono
310 311 mono = property(_mono_get, _mono_set) 312 313 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 314
315 - def _fg_high_get(self):
316 return self._fg_high
317
318 - def _fg_high_set(self, fg_high):
319 if fg_high is not None and not isinstance(fg_high, ForegroundHigh): 320 raise XYZValueError(_(u"Invalid argument type %s, "\ 321 u"libxyz.ui.color.ForegroundHigh instance "\ 322 u"expected." % type(fg_high))) 323 else: 324 self._fg_high = fg_high
325 326 fg_high = property(_fg_high_get, _fg_high_set) 327 328 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 329
330 - def _bg_high_get(self):
331 return self._bg_high
332
333 - def _bg_high_set(self, bg_high):
334 if bg_high is not None and not isinstance(bg_high, BackgroundHigh): 335 raise XYZValueError(_(u"Invalid argument type %s, "\ 336 u"libxyz.ui.color.BackgroundHigh instance "\ 337 u"expected." % type(bg_high))) 338 else: 339 self._bg_high = bg_high
340 341 bg_high = property(_bg_high_get, _bg_high_set) 342 343 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 344
345 - def get_palette(self, display=const.DEFAULT_DISPLAY_DRIVER):
346 """ 347 Return urwid-compatible palette tuple 348 """ 349 350 raw = display == "raw" 351 352 fg = self.fg.color 353 fg_attrs = self.fg_attrs 354 355 # Append attributes to foreground color 356 if fg_attrs is not None and is_lowui_ge_0_9_9() and raw: 357 fg = ",".join([fg] + [x.color for x in fg_attrs]) 358 359 bg = self.bg.color 360 mono = self.mono 361 362 if mono is not None: 363 mono = ",".join([x.color for x in mono]) 364 365 fg_high = self.fg_high 366 367 if fg_high is not None: 368 fg_high = fg_high.color 369 370 if fg_attrs is not None and is_lowui_ge_0_9_9() and raw: 371 fg_high = ",".join([fg_high] + [x.color for x in fg_attrs]) 372 373 bg_high = self.bg_high 374 375 if bg_high is not None: 376 bg_high = bg_high.color 377 378 result = (self.name, fg, bg, mono) 379 380 if is_lowui_ge_0_9_9() and raw: 381 result += (fg_high, bg_high) 382 383 return result
384 385 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 386
387 - def set_fg(self, fg):
388 """ 389 Set foreground color 390 """ 391 392 self.fg = fg
393 394 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 395
396 - def set_bg(self, bg):
397 """ 398 Set background color 399 """ 400 401 self.bg = bg
402 403 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 404
405 - def copy(self):
406 """ 407 Return copy of Palette instance 408 """ 409 410 return copy.deepcopy(self)
411 412 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 413
414 - def __call__(self, config):
415 new = self.copy() 416 417 fg, bg, fg_attrs, mono, fg_high, bg_high = self.convert(config) 418 419 if fg: 420 new.fg = fg 421 if bg: 422 new.bg = bg 423 if fg_attrs: 424 new.fg_attrs = fg_attrs 425 if mono: 426 new.mono = mono 427 if fg_high: 428 new.fg_high = fg_high 429 if bg_high: 430 new.bg_high = bg_high 431 432 return new
433