Package dtk :: Package ui :: Module label

Source Code for Module dtk.ui.label

  1  #! /usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (C) 2011 ~ 2012 Deepin, Inc. 
  5  #               2011 ~ 2012 Wang Yong 
  6  #  
  7  # Author:     Wang Yong <lazycat.manatee@gmail.com> 
  8  # Maintainer: Wang Yong <lazycat.manatee@gmail.com> 
  9  #  
 10  # This program is free software: you can redistribute it and/or modify 
 11  # it under the terms of the GNU General Public License as published by 
 12  # the Free Software Foundation, either version 3 of the License, or 
 13  # any later version. 
 14  #  
 15  # This program is distributed in the hope that it will be useful, 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  # GNU General Public License for more details. 
 19  #  
 20  # You should have received a copy of the GNU General Public License 
 21  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 22                    
 23  from constant import DEFAULT_FONT_SIZE, ALIGN_START, DEFAULT_FONT 
 24  from draw import draw_text, draw_hlinear 
 25  from keymap import get_keyevent_name 
 26  from theme import ui_theme 
 27  from utils import propagate_expose, get_content_size, is_double_click, is_left_button 
 28  import gtk 
 29  import pango  
 30  import pangocairo 
 31   
32 -class Label(gtk.EventBox):
33 ''' 34 Label. 35 36 @undocumented: button_press_label 37 @undocumented: button_release_label 38 @undocumented: motion_notify_label 39 @undocumented: key_press_label 40 @undocumented: focus_out_label 41 @undocumented: get_index_at_event 42 @undocumented: get_content_width 43 @undocumented: expose_label 44 @undocumented: draw_label_background 45 @undocumented: draw_label_text 46 @undocumented: update_size 47 ''' 48
49 - def __init__(self, 50 text, 51 text_color=None, 52 text_size=DEFAULT_FONT_SIZE, 53 text_x_align=ALIGN_START, 54 label_width=None, 55 enable_gaussian=False, 56 enable_select=True, 57 enable_double_click=True, 58 gaussian_radious=2, 59 border_radious=1, 60 wrap_width=None, 61 ):
62 ''' 63 Initialize Label class. 64 65 @param text: Label text. 66 @param text_color: Label text color, default is None. 67 @param text_size: Label text size, default is DEFAULT_FONT_SIZE. 68 @param text_x_align: Horizontal align option, default is ALIGN_START. 69 @param label_width: Label maximum width, default is None. 70 @param enable_gaussian: Default is False, if it is True, color option no effect, default gaussian effect is white text and black shadow. 71 @param enable_select: Default is True, label content can't select if it is False. 72 @param gaussian_radious: Radious of gaussian. 73 @param border_radious: Radious of border. 74 @param wrap_width: Wrap width. 75 ''' 76 # Init. 77 gtk.EventBox.__init__(self) 78 self.set_visible_window(False) 79 self.set_can_focus(True) # can focus to response key-press signal 80 self.label_width = label_width 81 self.enable_gaussian = enable_gaussian 82 self.enable_select = enable_select 83 self.enable_double_click = enable_double_click 84 self.select_start_index = self.select_end_index = 0 85 self.double_click_flag = False 86 self.left_click_flag = False 87 self.left_click_coordindate = None 88 self.drag_start_index = 0 89 self.drag_end_index = 0 90 self.wrap_width = wrap_width 91 92 self.text = text 93 self.text_size = text_size 94 if text_color == None: 95 self.text_color = ui_theme.get_color("label_text") 96 else: 97 self.text_color = text_color 98 self.text_select_color = ui_theme.get_color("label_select_text") 99 self.text_select_background = ui_theme.get_color("label_select_background") 100 101 if self.enable_gaussian: 102 self.gaussian_radious = gaussian_radious 103 self.border_radious = border_radious 104 self.gaussian_color="#000000" 105 self.border_color="#000000" 106 else: 107 self.gaussian_radious=None 108 self.border_radious=None 109 self.gaussian_color=None 110 self.border_color=None 111 112 self.text_x_align = text_x_align 113 114 self.update_size() 115 116 self.connect("expose-event", self.expose_label) 117 self.connect("button-press-event", self.button_press_label) 118 self.connect("button-release-event", self.button_release_label) 119 self.connect("motion-notify-event", self.motion_notify_label) 120 self.connect("key-press-event", self.key_press_label) 121 self.connect("focus-out-event", self.focus_out_label) 122 123 # Add keymap. 124 self.keymap = { 125 "Ctrl + c" : self.copy_to_clipboard, 126 }
127
128 - def copy_to_clipboard(self):
129 ''' 130 Copy select text to clipboard. 131 ''' 132 if self.select_start_index != self.select_end_index: 133 cut_text = self.text[self.select_start_index:self.select_end_index] 134 135 clipboard = gtk.Clipboard() 136 clipboard.set_text(cut_text)
137
138 - def button_press_label(self, widget, event):
139 ''' 140 Internal callback for `button-press-event` signal. 141 142 @param widget: Label widget. 143 @param event: Button press event. 144 ''' 145 if not self.enable_gaussian: 146 # Get input focus. 147 self.grab_focus() 148 149 # Select all when double click left button. 150 if is_double_click(event) and self.enable_double_click: 151 self.double_click_flag = True 152 self.select_all() 153 # Change cursor when click left button. 154 elif is_left_button(event): 155 self.left_click_flag = True 156 self.left_click_coordindate = (event.x, event.y) 157 158 self.drag_start_index = self.get_index_at_event(widget, event)
159
160 - def button_release_label(self, widget, event):
161 ''' 162 Internal callback for `button-release-event` signal. 163 164 @param widget: Label widget. 165 @param event: Button release event. 166 ''' 167 if not self.double_click_flag and self.left_click_coordindate == (event.x, event.y): 168 self.select_start_index = self.select_end_index = 0 169 self.queue_draw() 170 171 self.double_click_flag = False 172 self.left_click_flag = False
173
174 - def motion_notify_label(self, widget, event):
175 ''' 176 Internal callback for `motion-notify-event` signal. 177 178 @param widget: Label widget. 179 @param event: Motion notify event. 180 ''' 181 if not self.double_click_flag and self.left_click_flag and self.enable_select: 182 self.drag_end_index = self.get_index_at_event(widget, event) 183 184 self.select_start_index = min(self.drag_start_index, self.drag_end_index) 185 self.select_end_index = max(self.drag_start_index, self.drag_end_index) 186 187 self.queue_draw()
188
189 - def key_press_label(self, widget, event):
190 ''' 191 Internal callback for `key-press-event` signal. 192 193 @param widget: Label widget. 194 @param event: Key press event. 195 ''' 196 key_name = get_keyevent_name(event) 197 198 if self.keymap.has_key(key_name): 199 self.keymap[key_name]() 200 201 return False
202
203 - def focus_out_label(self, widget, event):
204 ''' 205 Internal callback for `focus-out-event` signal. 206 207 @param widget: Label widget. 208 @param event: Focus out event. 209 ''' 210 if self.select_start_index != self.select_end_index: 211 self.select_start_index = self.select_end_index = 0 212 213 self.queue_draw()
214
215 - def get_index_at_event(self, widget, event):
216 ''' 217 Internal function to get index at event. 218 219 @param widget: Label widget. 220 @param event: gtk.gdk.Event. 221 ''' 222 cr = widget.window.cairo_create() 223 context = pangocairo.CairoContext(cr) 224 layout = context.create_layout() 225 layout.set_font_description(pango.FontDescription("%s %s" % (DEFAULT_FONT, self.text_size))) 226 layout.set_text(self.text) 227 (text_width, text_height) = layout.get_pixel_size() 228 if int(event.x) > text_width: 229 return len(self.text) 230 else: 231 (x_index, y_index) = layout.xy_to_index(int(event.x) * pango.SCALE, 0) 232 return x_index
233
234 - def get_content_width(self, content):
235 ''' 236 Internal fucntion to get content width. 237 ''' 238 (content_width, content_height) = get_content_size(content, self.text_size, wrap_width=self.wrap_width) 239 return content_width
240
241 - def select_all(self):
242 ''' 243 Select all. 244 ''' 245 self.select_start_index = 0 246 self.select_end_index = len(self.text) 247 248 self.queue_draw()
249
250 - def expose_label(self, widget, event):
251 ''' 252 Internal callback for `expose-event` signal. 253 254 @param widget: Label widget. 255 @param event: Expose event. 256 ''' 257 cr = widget.window.cairo_create() 258 rect = widget.allocation 259 260 self.draw_label_background(cr, rect) 261 262 self.draw_label_text(cr, rect) 263 264 propagate_expose(widget, event) 265 266 return True
267
268 - def draw_label_background(self, cr, rect):
269 ''' 270 Inernal function to draw label background. 271 272 @param cr: Cairo context. 273 @param rect: Draw area. 274 @return: Always return True. 275 ''' 276 if self.select_start_index != self.select_end_index: 277 select_start_width = self.get_content_width(self.text[0:self.select_start_index]) 278 select_end_width = self.get_content_width(self.text[0:self.select_end_index]) 279 280 draw_hlinear(cr, 281 rect.x + select_start_width, 282 rect.y, 283 select_end_width - select_start_width, 284 rect.height, 285 [(0, (self.text_select_background.get_color(), 0)), 286 (0, (self.text_select_background.get_color(), 1))] 287 )
288
289 - def draw_label_text(self, cr, rect):
290 ''' 291 Internal fucntion to draw label text. 292 293 @param cr: Cairo context. 294 @param rect: Draw area. 295 ''' 296 if self.enable_gaussian: 297 label_color = "#FFFFFF" 298 else: 299 label_color = self.text_color.get_color() 300 301 if not self.get_sensitive(): 302 draw_text(cr, self.text, 303 rect.x, rect.y, rect.width, rect.height, 304 self.text_size, 305 ui_theme.get_color("disable_text").get_color(), 306 alignment=self.text_x_align, 307 gaussian_radious=self.gaussian_radious, 308 gaussian_color=self.gaussian_color, 309 border_radious=self.border_radious, 310 border_color=self.border_color, 311 wrap_width=self.wrap_width 312 ) 313 elif self.select_start_index == self.select_end_index: 314 draw_text(cr, self.text, 315 rect.x, rect.y, rect.width, rect.height, 316 self.text_size, 317 label_color, 318 alignment=self.text_x_align, 319 gaussian_radious=self.gaussian_radious, 320 gaussian_color=self.gaussian_color, 321 border_radious=self.border_radious, 322 border_color=self.border_color, 323 wrap_width=self.wrap_width 324 ) 325 else: 326 select_start_width = self.get_content_width(self.text[0:self.select_start_index]) 327 select_end_width = self.get_content_width(self.text[0:self.select_end_index]) 328 329 # Draw left text. 330 if self.text[0:self.select_start_index] != "": 331 draw_text(cr, self.text[0:self.select_start_index], 332 rect.x, rect.y, rect.width, rect.height, 333 self.text_size, 334 label_color, 335 alignment=self.text_x_align, 336 gaussian_radious=self.gaussian_radious, 337 gaussian_color=self.gaussian_color, 338 border_radious=self.border_radious, 339 border_color=self.border_color, 340 wrap_width=self.wrap_width 341 ) 342 343 # Draw middle text. 344 if self.text[self.select_start_index:self.select_end_index] != "": 345 draw_text(cr, self.text[self.select_start_index:self.select_end_index], 346 rect.x + select_start_width, rect.y, rect.width, rect.height, 347 self.text_size, 348 self.text_select_color.get_color(), 349 alignment=self.text_x_align, 350 gaussian_radious=self.gaussian_radious, 351 gaussian_color=self.gaussian_color, 352 border_radious=self.border_radious, 353 border_color=self.border_color, 354 wrap_width=self.wrap_width 355 ) 356 357 # Draw right text. 358 if self.text[self.select_end_index::] != "": 359 draw_text(cr, self.text[self.select_end_index::], 360 rect.x + select_end_width, rect.y, rect.width, rect.height, 361 self.text_size, 362 label_color, 363 alignment=self.text_x_align, 364 gaussian_radious=self.gaussian_radious, 365 gaussian_color=self.gaussian_color, 366 border_radious=self.border_radious, 367 border_color=self.border_color, 368 wrap_width=self.wrap_width 369 )
370
371 - def get_text(self):
372 ''' 373 Get text of label. 374 ''' 375 return self.text
376
377 - def set_text(self, text):
378 ''' 379 Set text with given value. 380 381 @param text: Label string. 382 ''' 383 self.text = text 384 self.update_size() 385 self.queue_draw()
386
387 - def update_size(self):
388 ''' 389 Internal function to update size. 390 ''' 391 if self.label_width == None: 392 (label_width, label_height) = get_content_size(self.text, self.text_size, wrap_width=self.wrap_width) 393 else: 394 (label_width, label_height) = get_content_size(self.text, self.text_size, wrap_width=self.wrap_width) 395 label_width = self.label_width 396 397 if self.enable_gaussian: 398 label_width += self.gaussian_radious * 2 399 label_height += self.gaussian_radious * 2 400 401 self.set_size_request(label_width, label_height)
402