Package dtk :: Package ui :: Module entry

Source Code for Module dtk.ui.entry

   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, DEFAULT_FONT 
  24  from contextlib import contextmanager  
  25  from draw import draw_hlinear 
  26  from keymap import get_keyevent_name 
  27  from locales import _ 
  28  from menu import Menu 
  29  from theme import ui_theme 
  30  import gobject 
  31  import gtk 
  32  import pango 
  33  import pangocairo 
  34  from utils import (propagate_expose, cairo_state, color_hex_to_cairo,  
  35                     get_content_size, is_double_click, is_right_button,  
  36                     is_left_button, alpha_color_hex_to_cairo, cairo_disable_antialias) 
37 38 -class Entry(gtk.EventBox):
39 ''' 40 Entry. 41 42 @undocumented: monitor_entry_content 43 @undocumented: realize_entry 44 @undocumented: key_press_entry 45 @undocumented: handle_key_press 46 @undocumented: handle_key_event 47 @undocumented: expose_entry 48 @undocumented: draw_entry_background 49 @undocumented: draw_entry_text 50 @undocumented: draw_entry_cursor 51 @undocumented: button_press_entry 52 @undocumented: handle_button_press 53 @undocumented: button_release_entry 54 @undocumented: motion_notify_entry 55 @undocumented: focus_in_entry 56 @undocumented: focus_out_entry 57 @undocumented: handle_focus_out 58 @undocumented: move_offsetx_right 59 @undocumented: move_offsetx_left 60 @undocumented: get_index_at_event 61 @undocumented: commit_entry 62 @undocumented: get_content_width 63 @undocumented: get_utf8_string 64 ''' 65 66 MOVE_LEFT = 1 67 MOVE_RIGHT = 2 68 MOVE_NONE = 3 69 70 __gsignals__ = { 71 "edit-alarm" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 72 "press-return" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 73 "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 74 "invalid-value" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 75 } 76
77 - def __init__(self, 78 content="", 79 padding_x=5, 80 padding_y=2, 81 text_color=ui_theme.get_color("entry_text"), 82 text_select_color=ui_theme.get_color("entry_select_text"), 83 background_select_color=ui_theme.get_shadow_color("entry_select_background"), 84 font_size=DEFAULT_FONT_SIZE, 85 ):
86 ''' 87 Initialize Entry class. 88 89 @param content: Entry initialize content, default is \"\". 90 @param padding_x: Horizontal padding value, default is 5 pixel. 91 @param padding_y: Vertical padding value, default is 2 pixel. 92 @param text_color: Color of text in normal status. 93 @param text_select_color: Color of text in select status. 94 @param background_select_color: Color of background in select status. 95 @param font_size: Entry font size, default is DEFAULT_FONT_SIZE. 96 ''' 97 # Init. 98 gtk.EventBox.__init__(self) 99 self.set_visible_window(False) 100 self.set_can_focus(True) # can focus to response key-press signal 101 self.im = gtk.IMMulticontext() 102 self.font_size = font_size 103 self.text_color = text_color 104 self.text_select_color = text_select_color 105 self.background_select_color = background_select_color 106 self.padding_x = padding_x 107 self.padding_y = padding_y 108 self.move_direction = self.MOVE_NONE 109 self.double_click_flag = False 110 self.left_click_flag = False 111 self.left_click_coordindate = None 112 self.drag_start_index = 0 113 self.drag_end_index = 0 114 self.grab_focus_flag = False 115 self.editable_flag = True 116 self.check_text = None 117 self.cursor_visible_flag = True 118 self.right_menu_visible_flag = True 119 self.select_area_visible_flag = True 120 121 self.content = content 122 self.cursor_index = len(self.content) 123 self.select_start_index = self.select_end_index = self.cursor_index 124 self.offset_x = 0 125 126 # Add keymap. 127 self.keymap = { 128 "Left" : self.move_to_left, 129 "Right" : self.move_to_right, 130 "Home" : self.move_to_start, 131 "End" : self.move_to_end, 132 "BackSpace" : self.backspace, 133 "Delete" : self.delete, 134 "Shift + Left" : self.select_to_left, 135 "Shift + Right" : self.select_to_right, 136 "Shift + Home" : self.select_to_start, 137 "Shift + End" : self.select_to_end, 138 "Ctrl + a" : self.select_all, 139 "Ctrl + x" : self.cut_to_clipboard, 140 "Ctrl + c" : self.copy_to_clipboard, 141 "Ctrl + v" : self.paste_from_clipboard, 142 "Return" : self.press_return} 143 144 # Add menu. 145 self.right_menu = Menu( 146 [(None, _("Cut"), self.cut_to_clipboard), 147 (None, _("Copy"), self.copy_to_clipboard), 148 (None, _("Paste"), self.paste_from_clipboard), 149 (None, _("Select all"), self.select_all)], 150 True) 151 152 # Connect signal. 153 self.connect_after("realize", self.realize_entry) 154 self.connect("key-press-event", self.key_press_entry) 155 self.connect("expose-event", self.expose_entry) 156 self.connect("button-press-event", self.button_press_entry) 157 self.connect("button-release-event", self.button_release_entry) 158 self.connect("motion-notify-event", self.motion_notify_entry) 159 self.connect("focus-in-event", self.focus_in_entry) 160 self.connect("focus-out-event", self.focus_out_entry) 161 162 self.im.connect("commit", lambda im, input_text: self.commit_entry(input_text))
163
164 - def set_editable(self, editable):
165 ''' 166 Set entry editable status. 167 168 @param editable: If it is True, entry can edit, else entry not allow edit. 169 ''' 170 self.editable_flag = editable
171 172 @contextmanager
173 - def monitor_entry_content(self):
174 ''' 175 Internal function to monitor entry content. 176 ''' 177 old_text = self.get_text() 178 try: 179 yield 180 except Exception, e: 181 print 'monitor_entry_content error %s' % e 182 else: 183 new_text = self.get_text() 184 if self.check_text == None or self.check_text(new_text): 185 if old_text != new_text: 186 self.emit("changed", new_text) 187 else: 188 self.emit("invalid-value", new_text) 189 self.set_text(old_text)
190
191 - def is_editable(self):
192 ''' 193 Whether entry is editable. 194 195 @return: Return True if entry editable, else return False. 196 ''' 197 if not self.editable_flag: 198 self.emit("edit-alarm") 199 200 return self.editable_flag
201
202 - def set_text(self, text):
203 ''' 204 Set entry text. 205 206 @param text: Entry text string. 207 ''' 208 if self.is_editable(): 209 with self.monitor_entry_content(): 210 if text != None: 211 self.content = text 212 self.cursor_index = len(self.content) 213 self.select_start_index = self.select_end_index = self.cursor_index 214 215 text_width = self.get_content_width(self.content) 216 rect = self.get_allocation() 217 218 if text_width > rect.width - self.padding_x * 2 > 0: 219 self.offset_x = text_width - rect.width + self.padding_x * 2 220 else: 221 self.offset_x = 0 222 223 self.queue_draw()
224
225 - def get_text(self):
226 ''' 227 Get entry text. 228 229 @return: Return entry text string. 230 ''' 231 return self.content
232
233 - def realize_entry(self, widget):
234 ''' 235 Internal callback for `realize` signal. 236 ''' 237 text_width = self.get_content_width(self.content) 238 rect = self.get_allocation() 239 240 if text_width > rect.width - self.padding_x * 2 > 0: 241 self.offset_x = text_width - rect.width + self.padding_x * 2 242 else: 243 self.offset_x = 0
244
245 - def key_press_entry(self, widget, event):
246 ''' 247 Internal callback for `key-press-event` signal. 248 ''' 249 self.handle_key_press(widget, event)
250
251 - def handle_key_press(self, widget, event):
252 ''' 253 Internal function to handle key press. 254 ''' 255 # Pass key to IMContext. 256 input_method_filt = self.im.filter_keypress(event) 257 if not input_method_filt: 258 self.handle_key_event(event) 259 260 return False
261
262 - def handle_key_event(self, event):
263 ''' 264 Internal function to handle key event. 265 ''' 266 key_name = get_keyevent_name(event) 267 268 if self.keymap.has_key(key_name): 269 self.keymap[key_name]()
270
271 - def clear_select_status(self):
272 ''' 273 Clear entry select status. 274 ''' 275 self.select_start_index = self.select_end_index = self.cursor_index 276 self.move_direction = self.MOVE_NONE
277
278 - def move_to_start(self):
279 ''' 280 Move cursor to start position of entry. 281 ''' 282 self.offset_x = 0 283 self.cursor_index = 0 284 285 self.clear_select_status() 286 287 self.queue_draw()
288
289 - def move_to_end(self):
290 ''' 291 Move cursor to end position of entry. 292 ''' 293 text_width = self.get_content_width(self.content) 294 rect = self.get_allocation() 295 if text_width > rect.width - self.padding_x * 2 > 0: 296 self.offset_x = text_width - (rect.width - self.padding_x * 2) 297 self.cursor_index = len(self.content) 298 299 self.clear_select_status() 300 301 self.queue_draw()
302
303 - def move_to_left(self):
304 ''' 305 Backward cursor one char. 306 ''' 307 # Avoid change focus to other widget in parent. 308 if self.keynav_failed(gtk.DIR_LEFT): 309 self.get_toplevel().set_focus_child(self) 310 311 if self.select_start_index != self.select_end_index: 312 self.cursor_index = self.select_start_index 313 select_start_width = self.get_content_width(self.content[0:self.select_start_index]) 314 315 self.clear_select_status() 316 317 if select_start_width < self.offset_x: 318 self.offset_x = select_start_width 319 320 self.queue_draw() 321 elif self.cursor_index > 0: 322 self.cursor_index -= len(self.get_utf8_string(self.content[0:self.cursor_index], -1)) 323 324 text_width = self.get_content_width(self.content[0:self.cursor_index]) 325 if text_width - self.offset_x < 0: 326 self.offset_x = text_width 327 328 self.queue_draw()
329
330 - def move_to_right(self):
331 ''' 332 Forward cursor one char. 333 ''' 334 # Avoid change focus to other widget in parent. 335 if self.keynav_failed(gtk.DIR_RIGHT): 336 self.get_toplevel().set_focus_child(self) 337 338 if self.select_start_index != self.select_end_index: 339 self.cursor_index = self.select_end_index 340 select_end_width = self.get_content_width(self.content[0:self.select_end_index]) 341 342 self.clear_select_status() 343 344 rect = self.get_allocation() 345 if select_end_width > self.offset_x + rect.width - self.padding_x * 2: 346 self.offset_x = select_end_width - rect.width + self.padding_x * 2 347 348 self.queue_draw() 349 elif self.cursor_index < len(self.content): 350 self.cursor_index += len(self.content[self.cursor_index::].decode('utf-8')[0].encode('utf-8')) 351 352 text_width = self.get_content_width(self.content[0:self.cursor_index]) 353 rect = self.get_allocation() 354 if text_width - self.offset_x > rect.width - self.padding_x * 2: 355 self.offset_x = text_width - (rect.width - self.padding_x * 2) 356 357 self.queue_draw()
358
359 - def backspace(self):
360 ''' 361 Do backspace action. 362 ''' 363 if self.is_editable(): 364 with self.monitor_entry_content(): 365 if self.select_start_index != self.select_end_index: 366 self.delete() 367 elif self.cursor_index > 0: 368 old_insert_width = self.get_content_width(self.content[0:self.cursor_index]) 369 delete_char = self.get_utf8_string(self.content[0:self.cursor_index], -1) 370 self.cursor_index -= len(delete_char) 371 372 self.content = self.content[0:self.cursor_index] + self.content[self.cursor_index + len(delete_char)::] 373 text_width = self.get_content_width(self.content) 374 insert_width = self.get_content_width(self.content[0:self.cursor_index]) 375 rect = self.get_allocation() 376 if text_width < rect.width - self.padding_x * 2: 377 self.offset_x = 0 378 else: 379 self.offset_x += insert_width - old_insert_width 380 381 self.queue_draw()
382
383 - def select_all(self):
384 ''' 385 Select all text of entry. 386 ''' 387 self.select_start_index = 0 388 self.select_end_index = len(self.content) 389 390 self.queue_draw()
391
392 - def cut_to_clipboard(self):
393 ''' 394 Cut selected text to clipboard. 395 ''' 396 if self.select_start_index != self.select_end_index: 397 cut_text = self.content[self.select_start_index:self.select_end_index] 398 399 if self.is_editable(): 400 with self.monitor_entry_content(): 401 self.delete() 402 403 clipboard = gtk.Clipboard() 404 clipboard.set_text(cut_text)
405
406 - def copy_to_clipboard(self):
407 ''' 408 Copy selected text to clipboard. 409 ''' 410 if self.select_start_index != self.select_end_index: 411 cut_text = self.content[self.select_start_index:self.select_end_index] 412 413 clipboard = gtk.Clipboard() 414 clipboard.set_text(cut_text)
415
416 - def paste_from_clipboard(self):
417 ''' 418 Paste text to entry from clipboard. 419 ''' 420 if self.is_editable(): 421 with self.monitor_entry_content(): 422 clipboard = gtk.Clipboard() 423 clipboard.request_text(lambda clipboard, text, data: self.commit_entry('\\n'.join(text.split('\n'))))
424
425 - def press_return(self):
426 ''' 427 Do return action. 428 ''' 429 self.emit("press-return")
430
431 - def select_to_left(self):
432 ''' 433 Select text to left char. 434 ''' 435 if self.select_start_index != self.select_end_index: 436 if self.move_direction == self.MOVE_LEFT: 437 if self.select_start_index > 0: 438 self.select_start_index -= len(self.get_utf8_string(self.content[0:self.select_start_index], -1)) 439 select_start_width = self.get_content_width(self.content[0:self.select_start_index]) 440 if select_start_width < self.offset_x: 441 self.offset_x = select_start_width 442 else: 443 self.select_end_index -= len(self.get_utf8_string(self.content[0:self.select_end_index], -1)) 444 445 select_end_width = self.get_content_width(self.content[0:self.select_end_index]) 446 if select_end_width < self.offset_x: 447 self.offset_x = select_end_width 448 else: 449 self.select_end_index = self.cursor_index 450 self.select_start_index = self.cursor_index - len(self.get_utf8_string(self.content[0:self.cursor_index], -1)) 451 self.move_direction = self.MOVE_LEFT 452 453 self.queue_draw()
454
455 - def select_to_right(self):
456 ''' 457 Select text to right char. 458 ''' 459 if self.select_start_index != self.select_end_index: 460 rect = self.get_allocation() 461 462 if self.move_direction == self.MOVE_RIGHT: 463 if self.select_end_index < len(self.content): 464 self.select_end_index += len(self.get_utf8_string(self.content[self.select_end_index::], 0)) 465 466 select_end_width = self.get_content_width(self.content[0:self.select_end_index]) 467 if select_end_width > self.offset_x + rect.width - self.padding_x * 2: 468 self.offset_x = select_end_width - rect.width + self.padding_x * 2 469 else: 470 self.select_start_index += len(self.get_utf8_string(self.content[self.select_start_index::], 0)) 471 select_start_width = self.get_content_width(self.content[0:self.select_start_index]) 472 if select_start_width > self.offset_x + rect.width - self.padding_x * 2: 473 self.offset_x = select_start_width - rect.width + self.padding_x * 2 474 else: 475 if self.select_end_index < len(self.content): 476 self.select_start_index = self.cursor_index 477 self.select_end_index = self.cursor_index + len(self.get_utf8_string(self.content[self.select_end_index::], 0)) 478 self.move_direction = self.MOVE_RIGHT 479 480 self.queue_draw()
481
482 - def select_to_start(self):
483 ''' 484 Select text to start position. 485 ''' 486 if self.select_start_index != self.select_end_index: 487 if self.move_direction == self.MOVE_LEFT: 488 self.select_start_index = 0 489 else: 490 self.select_end_index = self.select_start_index 491 self.select_start_index = 0 492 493 self.move_direction = self.MOVE_LEFT 494 else: 495 self.select_start_index = 0 496 self.select_end_index = self.cursor_index 497 498 self.move_direction = self.MOVE_LEFT 499 500 self.offset_x = 0 501 502 self.queue_draw()
503
504 - def select_to_end(self):
505 ''' 506 Select text to end position. 507 ''' 508 if self.select_start_index != self.select_end_index: 509 if self.move_direction == self.MOVE_RIGHT: 510 self.select_end_index = len(self.content) 511 else: 512 self.select_start_index = self.select_end_index 513 self.select_end_index = len(self.content) 514 515 self.move_direction = self.MOVE_RIGHT 516 else: 517 self.select_start_index = self.cursor_index 518 self.select_end_index = len(self.content) 519 520 self.move_direction = self.MOVE_RIGHT 521 522 rect = self.get_allocation() 523 select_end_width = self.get_content_width(self.content) 524 if select_end_width > self.offset_x + rect.width - self.padding_x * 2: 525 self.offset_x = select_end_width - rect.width + self.padding_x * 2 526 else: 527 self.offset_x = 0 528 529 self.queue_draw()
530
531 - def delete(self):
532 ''' 533 Delete selected text. 534 ''' 535 if self.is_editable() and self.select_start_index != self.select_end_index: 536 with self.monitor_entry_content(): 537 rect = self.get_allocation() 538 539 self.cursor_index = self.select_start_index 540 541 select_start_width = self.get_content_width(self.content[0:self.select_start_index]) 542 select_end_width = self.get_content_width(self.content[0:self.select_end_index]) 543 544 self.cursor_index = self.select_start_index 545 if select_start_width < self.offset_x: 546 if select_end_width < self.offset_x + rect.width - self.padding_x * 2: 547 self.offset_x = max(select_start_width + self.offset_x - select_end_width, 0) 548 else: 549 self.offset_x = 0 550 551 self.content = self.content[0:self.select_start_index] + self.content[self.select_end_index::] 552 553 self.select_start_index = self.select_end_index = self.cursor_index 554 555 self.queue_draw()
556
557 - def expose_entry(self, widget, event):
558 ''' 559 Internal callback for `expose-event` signal. 560 ''' 561 # Init. 562 cr = widget.window.cairo_create() 563 rect = widget.allocation 564 565 # Draw background. 566 if self.get_sensitive(): 567 self.draw_entry_background(cr, rect) 568 569 # Draw text. 570 self.draw_entry_text(cr, rect) 571 572 # Draw cursor. 573 if self.cursor_visible_flag and self.get_sensitive(): 574 self.draw_entry_cursor(cr, rect) 575 576 # Propagate expose. 577 propagate_expose(widget, event) 578 579 return True
580
581 - def draw_entry_background(self, cr, rect):
582 ''' 583 Internal function to draw entry background. 584 ''' 585 x, y, w, h = rect.x, rect.y, rect.width, rect.height 586 587 if self.select_start_index != self.select_end_index and self.select_area_visible_flag: 588 select_start_width = self.get_content_width(self.content[0:self.select_start_index]) 589 select_end_width = self.get_content_width(self.content[0:self.select_end_index]) 590 591 draw_hlinear(cr, 592 x + self.padding_x + max(select_start_width - self.offset_x, 0), 593 y + self.padding_y, 594 min(select_end_width, self.offset_x + w - self.padding_x * 2) - max(select_start_width, self.offset_x), 595 h - self.padding_y * 2, 596 self.background_select_color.get_color_info())
597
598 - def draw_entry_text(self, cr, rect):
599 ''' 600 Internal function to draw entry text. 601 ''' 602 x, y, w, h = rect.x, rect.y, rect.width, rect.height 603 with cairo_state(cr): 604 # Clip text area first. 605 draw_x = x + self.padding_x 606 draw_y = y + self.padding_y 607 draw_width = w - self.padding_x * 2 608 draw_height = h - self.padding_y * 2 609 cr.rectangle(draw_x, draw_y, draw_width, draw_height) 610 cr.clip() 611 612 # Create pangocairo context. 613 context = pangocairo.CairoContext(cr) 614 615 # Set layout. 616 layout = context.create_layout() 617 layout.set_font_description(pango.FontDescription("%s %s" % (DEFAULT_FONT, self.font_size))) 618 619 if not self.get_sensitive(): 620 # Set text. 621 layout.set_text(self.content) 622 623 # Get text size. 624 (text_width, text_height) = layout.get_pixel_size() 625 626 # Move text. 627 cr.move_to(draw_x - self.offset_x, 628 draw_y + (draw_height - text_height) / 2) 629 630 # Draw text. 631 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_text").get_color())) 632 context.update_layout(layout) 633 context.show_layout(layout) 634 elif self.select_start_index != self.select_end_index and self.select_area_visible_flag: 635 # Get string. 636 before_select_str = self.content[0:self.select_start_index] 637 select_str = self.content[self.select_start_index:self.select_end_index] 638 after_select_str = self.content[self.select_end_index::] 639 640 # Build render list. 641 render_list = [] 642 643 layout.set_text(before_select_str) 644 (before_select_width, before_select_height) = layout.get_pixel_size() 645 render_list.append((before_select_str, 0, before_select_height, self.text_color)) 646 647 layout.set_text(select_str) 648 (select_width, select_height) = layout.get_pixel_size() 649 render_list.append((select_str, before_select_width, select_height, self.text_select_color)) 650 651 layout.set_text(after_select_str) 652 (after_select_width, after_select_height) = layout.get_pixel_size() 653 render_list.append((after_select_str, before_select_width + select_width, after_select_height, self.text_color)) 654 655 # Render. 656 for (string, offset, text_height, text_color) in render_list: 657 layout.set_text(string) 658 cr.move_to(draw_x - self.offset_x + offset, 659 draw_y + (draw_height - text_height) / 2) 660 cr.set_source_rgb(*color_hex_to_cairo(text_color.get_color())) 661 context.update_layout(layout) 662 context.show_layout(layout) 663 else: 664 # Set text. 665 layout.set_text(self.content) 666 667 # Get text size. 668 (text_width, text_height) = layout.get_pixel_size() 669 670 # Move text. 671 cr.move_to(draw_x - self.offset_x, 672 draw_y + (draw_height - text_height) / 2) 673 674 # Draw text. 675 cr.set_source_rgb(*color_hex_to_cairo(self.text_color.get_color())) 676 context.update_layout(layout) 677 context.show_layout(layout)
678
679 - def draw_entry_cursor(self, cr, rect):
680 ''' 681 Internal function to draw entry cursor. 682 ''' 683 if self.grab_focus_flag and self.select_start_index == self.select_end_index: 684 # Init. 685 x, y, w, h = rect.x, rect.y, rect.width, rect.height 686 left_str = self.content[0:self.cursor_index] 687 left_str_width = self.get_content_width(left_str) 688 padding_y = (h - (get_content_size("Height", self.font_size)[-1])) / 2 689 690 # Draw cursor. 691 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("entry_cursor").get_color())) 692 cr.rectangle(x + self.padding_x + left_str_width - self.offset_x, 693 y + padding_y, 694 1, 695 h - padding_y * 2 696 ) 697 cr.fill()
698
699 - def button_press_entry(self, widget, event):
700 ''' 701 Internal callback for `button-press-event` signal. 702 ''' 703 self.handle_button_press(widget, event)
704
705 - def handle_button_press(self, widget, event):
706 ''' 707 Internal function to handle button press. 708 ''' 709 # Get input focus. 710 self.grab_focus() 711 712 # Hide right menu immediately. 713 self.right_menu.hide() 714 715 # Select all when double click left button. 716 if is_double_click(event): 717 self.double_click_flag = True 718 self.select_all() 719 # Show right menu when click right button. 720 elif is_right_button(event): 721 if self.right_menu_visible_flag: 722 (wx, wy) = self.window.get_root_origin() 723 (cx, cy, modifier) = self.window.get_pointer() 724 self.right_menu.show((cx + wx, cy + wy)) 725 # Change cursor when click left button. 726 elif is_left_button(event): 727 self.left_click_flag = True 728 self.left_click_coordindate = (event.x, event.y) 729 730 self.drag_start_index = self.get_index_at_event(widget, event)
731
732 - def button_release_entry(self, widget, event):
733 ''' 734 Internal callback for `button-release-event` signal. 735 ''' 736 if not self.double_click_flag and self.left_click_coordindate == (event.x, event.y): 737 self.cursor_index = self.get_index_at_event(widget, event) 738 self.select_start_index = self.select_end_index = self.cursor_index 739 self.queue_draw() 740 741 self.double_click_flag = False 742 self.left_click_flag = False
743
744 - def motion_notify_entry(self, widget, event):
745 ''' 746 Internal callback for `motion-notify-event` signal. 747 ''' 748 if not self.double_click_flag and self.left_click_flag: 749 self.cursor_index = self.drag_start_index 750 self.drag_end_index = self.get_index_at_event(widget, event) 751 752 self.select_start_index = min(self.drag_start_index, self.drag_end_index) 753 self.select_end_index = max(self.drag_start_index, self.drag_end_index) 754 755 if self.drag_start_index < self.drag_end_index: 756 rect = self.get_allocation() 757 if int(event.x) > rect.width: 758 self.move_offsetx_right(widget, event) 759 else: 760 if int(event.x) < 0: 761 self.move_offsetx_left(widget, event) 762 763 self.queue_draw()
764
765 - def focus_in_entry(self, widget, event):
766 ''' 767 Internal callback for `focus-in-event` signal. 768 ''' 769 self.grab_focus_flag = True 770 771 # Focus in IMContext. 772 self.im.set_client_window(widget.window) 773 self.im.focus_in() 774 775 self.queue_draw()
776
777 - def focus_out_entry(self, widget, event):
778 ''' 779 Internal callback for `focus-out-event` signal. 780 ''' 781 self.handle_focus_out(widget, event)
782
783 - def handle_focus_out(self, widget, event):
784 ''' 785 Internal function to handle focus out. 786 ''' 787 self.grab_focus_flag = False 788 789 # Focus out IMContext. 790 self.im.focus_out() 791 792 self.queue_draw()
793
794 - def move_offsetx_right(self, widget, event):
795 ''' 796 Internal function to move offset_x to right. 797 ''' 798 text_width = self.get_content_width(self.content) 799 rect = self.get_allocation() 800 if self.offset_x + rect.width - self.padding_x * 2 < text_width: 801 cr = widget.window.cairo_create() 802 context = pangocairo.CairoContext(cr) 803 layout = context.create_layout() 804 layout.set_font_description(pango.FontDescription("%s %s" % (DEFAULT_FONT, self.font_size))) 805 layout.set_text(self.content) 806 (text_width, text_height) = layout.get_pixel_size() 807 (x_index, y_index) = layout.xy_to_index((self.offset_x + rect.width - self.padding_x * 2) * pango.SCALE, 0) 808 809 self.offset_x += len(self.get_utf8_string(self.content[x_index::], 0))
810
811 - def move_offsetx_left(self, widget, event):
812 ''' 813 Internal function to move offset_x to left. 814 ''' 815 if self.offset_x > 0: 816 cr = widget.window.cairo_create() 817 context = pangocairo.CairoContext(cr) 818 layout = context.create_layout() 819 layout.set_font_description(pango.FontDescription("%s %s" % (DEFAULT_FONT, self.font_size))) 820 layout.set_text(self.content) 821 (text_width, text_height) = layout.get_pixel_size() 822 (x_index, y_index) = layout.xy_to_index((self.offset_x + self.padding_x) * pango.SCALE, 0) 823 824 self.offset_x -= len(self.get_utf8_string(self.content[0:x_index], -1))
825
826 - def get_index_at_event(self, widget, event):
827 ''' 828 Internal function to get index at event. 829 ''' 830 cr = widget.window.cairo_create() 831 context = pangocairo.CairoContext(cr) 832 layout = context.create_layout() 833 layout.set_font_description(pango.FontDescription("%s %s" % (DEFAULT_FONT, self.font_size))) 834 layout.set_text(self.content) 835 (text_width, text_height) = layout.get_pixel_size() 836 if int(event.x) + self.offset_x - self.padding_x > text_width: 837 return len(self.content) 838 else: 839 (x_index, y_index) = layout.xy_to_index((int(event.x) + self.offset_x - self.padding_x) * pango.SCALE, 0) 840 return x_index
841
842 - def commit_entry(self, input_text):
843 ''' 844 Internal callback for `commit` signal. 845 ''' 846 if self.is_editable(): 847 with self.monitor_entry_content(): 848 if self.select_start_index != self.select_end_index: 849 self.delete() 850 851 self.content = self.content[0:self.cursor_index] + input_text + self.content[self.cursor_index::] 852 self.cursor_index += len(input_text) 853 854 text_width = self.get_content_width(self.content) 855 rect = self.get_allocation() 856 if text_width <= rect.width - self.padding_x * 2: 857 self.offset_x = 0 858 elif self.cursor_index == len(self.content): 859 self.offset_x = text_width - (rect.width - self.padding_x * 2) 860 else: 861 old_text_width = self.get_content_width(self.content[0:self.cursor_index - len(input_text)]) 862 input_text_width = self.get_content_width(input_text) 863 if old_text_width - self.offset_x + input_text_width > rect.width - self.padding_x * 2: 864 new_text_width = self.get_content_width(self.content[0:self.cursor_index]) 865 self.offset_x = new_text_width - (rect.width - self.padding_x * 2) 866 867 self.queue_draw()
868
869 - def get_content_width(self, content):
870 ''' 871 Internal function to get content width. 872 ''' 873 (content_width, content_height) = get_content_size(content, self.font_size) 874 return content_width
875
876 - def get_utf8_string(self, content, index):
877 ''' 878 Internal to get utf8 string. 879 ''' 880 try: 881 return list(content.decode('utf-8'))[index].encode('utf-8') 882 except Exception, e: 883 print "get_utf8_string got error: %s" % (e) 884 return ""
885 886 gobject.type_register(Entry)
887 888 -class TextEntry(gtk.VBox):
889 ''' 890 Text entry. 891 892 @undocumented: set_sensitive 893 @undocumented: emit_action_active_signal 894 @undocumented: expose_text_entry 895 ''' 896 897 __gsignals__ = { 898 "action-active" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 899 } 900
901 - def __init__(self, 902 content="", 903 action_button=None, 904 background_color = ui_theme.get_alpha_color("text_entry_background"), 905 acme_color = ui_theme.get_alpha_color("text_entry_acme"), 906 point_color = ui_theme.get_alpha_color("text_entry_point"), 907 frame_point_color = ui_theme.get_alpha_color("text_entry_frame_point"), 908 frame_color = ui_theme.get_alpha_color("text_entry_frame"), 909 ):
910 ''' 911 Initialize InputEntry class. 912 913 @param content: Initialize entry text, default is \"\". 914 @param action_button: Extra button add at right side of text entry, default is None. 915 @param background_color: Color of text entry background. 916 @param acme_color: Acme point color of text entry. 917 @param point_color: Pointer color of text entry. 918 @param frame_point_color: Frame pointer color of text entry. 919 @param frame_color: Frame color of text entry. 920 ''' 921 # Init. 922 gtk.VBox.__init__(self) 923 self.align = gtk.Alignment() 924 self.align.set(0.5, 0.5, 1.0, 1.0) 925 self.action_button = action_button 926 self.h_box = gtk.HBox() 927 self.entry = Entry(content) 928 self.background_color = background_color 929 self.acme_color = acme_color 930 self.point_color = point_color 931 self.frame_point_color = frame_point_color 932 self.frame_color = frame_color 933 934 self.pack_start(self.align, False, False) 935 self.align.add(self.h_box) 936 self.h_box.pack_start(self.entry) 937 if action_button: 938 self.action_align = gtk.Alignment() 939 self.action_align.set(0.0, 0.5, 0, 0) 940 self.action_align.set_padding(0, 0, 0, self.entry.padding_x) 941 self.action_align.add(self.action_button) 942 943 self.h_box.pack_start(self.action_align, False, False) 944 945 self.action_button.connect("clicked", lambda w: self.emit_action_active_signal()) 946 947 # Handle signal. 948 self.align.connect("expose-event", self.expose_text_entry)
949
950 - def set_sensitive(self, sensitive):
951 ''' 952 Internal function to wrap function `set_sensitive`. 953 ''' 954 super(TextEntry, self).set_sensitive(sensitive) 955 self.entry.set_sensitive(sensitive)
956
957 - def emit_action_active_signal(self):
958 ''' 959 Internal callback for `action-active` signal. 960 ''' 961 self.emit("action-active", self.get_text())
962
963 - def expose_text_entry(self, widget, event):
964 ''' 965 Internal callback for `expose-event` signal. 966 ''' 967 # Init. 968 cr = widget.window.cairo_create() 969 rect = widget.allocation 970 x, y, w, h = rect.x, rect.y, rect.width, rect.height 971 972 # Draw background. 973 with cairo_state(cr): 974 cr.rectangle(x + 2, y, w - 4, 1) 975 cr.rectangle(x + 1, y + 1, w - 2, 1) 976 cr.rectangle(x, y + 2, w, h - 4) 977 cr.rectangle(x + 2, y + h - 1, w - 4, 1) 978 cr.rectangle(x + 1, y + h - 2, w - 2, 1) 979 cr.clip() 980 981 cr.set_source_rgba(*alpha_color_hex_to_cairo(self.background_color.get_color_info())) 982 cr.rectangle(x, y, w, h) 983 cr.fill() 984 985 # Draw background four acme points. 986 cr.set_source_rgba(*alpha_color_hex_to_cairo(self.acme_color.get_color_info())) 987 cr.rectangle(x, y, 1, 1) 988 cr.rectangle(x + w - 1, y, 1, 1) 989 cr.rectangle(x, y + h - 1, 1, 1) 990 cr.rectangle(x + w - 1, y + h - 1, 1, 1) 991 cr.fill() 992 993 # Draw background eight points. 994 cr.set_source_rgba(*alpha_color_hex_to_cairo(self.point_color.get_color_info())) 995 996 cr.rectangle(x + 1, y, 1, 1) 997 cr.rectangle(x, y + 1, 1, 1) 998 999 cr.rectangle(x + w - 2, y, 1, 1) 1000 cr.rectangle(x + w - 1, y + 1, 1, 1) 1001 1002 cr.rectangle(x, y + h - 2, 1, 1) 1003 cr.rectangle(x + 1, y + h - 1, 1, 1) 1004 1005 cr.rectangle(x + w - 1, y + h - 2, 1, 1) 1006 cr.rectangle(x + w - 2, y + h - 1, 1, 1) 1007 1008 cr.fill() 1009 1010 # Draw frame point. 1011 cr.set_source_rgba(*alpha_color_hex_to_cairo(self.frame_point_color.get_color_info())) 1012 1013 cr.rectangle(x + 1, y, 1, 1) 1014 cr.rectangle(x, y + 1, 1, 1) 1015 1016 cr.rectangle(x + w - 2, y, 1, 1) 1017 cr.rectangle(x + w - 1, y + 1, 1, 1) 1018 1019 cr.rectangle(x, y + h - 2, 1, 1) 1020 cr.rectangle(x + 1, y + h - 1, 1, 1) 1021 1022 cr.rectangle(x + w - 1, y + h - 2, 1, 1) 1023 cr.rectangle(x + w - 2, y + h - 1, 1, 1) 1024 1025 cr.fill() 1026 1027 # Draw frame. 1028 cr.set_source_rgba(*alpha_color_hex_to_cairo(self.frame_color.get_color_info())) 1029 1030 cr.rectangle(x + 2, y, w - 4, 1) 1031 cr.rectangle(x, y + 2, 1, h - 4) 1032 cr.rectangle(x + 2, y + h - 1, w - 4, 1) 1033 cr.rectangle(x + w - 1, y + 2, 1, h - 4) 1034 1035 cr.fill() 1036 1037 propagate_expose(widget, event) 1038 1039 return True
1040
1041 - def set_size(self, width, height):
1042 ''' 1043 Set text entry size with given value. 1044 1045 @param width: New width of text entry. 1046 @param height: New height of text entry. 1047 ''' 1048 self.set_size_request(width, height) 1049 1050 action_button_width = 0 1051 if self.action_button: 1052 action_button_width = self.action_button.get_size_request()[-1] + self.entry.padding_x 1053 1054 self.entry.set_size_request(width - 2 - action_button_width, height - 2)
1055
1056 - def set_editable(self, editable):
1057 ''' 1058 Set editable status of text entry. 1059 1060 @param editable: Text entry can editable if option is True, else can't edit. 1061 ''' 1062 self.entry.set_editable(editable)
1063
1064 - def set_text(self, text):
1065 ''' 1066 Set text of text entry. 1067 1068 @param text: Text entry string. 1069 ''' 1070 self.entry.set_text(text)
1071
1072 - def get_text(self):
1073 ''' 1074 Get text of text entry. 1075 1076 @return: Return text of text entry. 1077 ''' 1078 return self.entry.get_text()
1079
1080 - def focus_input(self):
1081 ''' 1082 Focus input cursor. 1083 ''' 1084 self.entry.grab_focus()
1085 1086 gobject.type_register(TextEntry)
1087 1088 -class InputEntry(gtk.VBox):
1089 ''' 1090 Text entry. 1091 1092 Generically speaking, InputEntry is similar L{ I{TextEntry} <TextEntry>}, 1093 1094 only difference between two class is ui style, internal logic is same. 1095 1096 @undocumented: set_sensitive 1097 @undocumented: emit_action_active_signal 1098 @undocumented: expose_input_entry 1099 ''' 1100 1101 __gsignals__ = { 1102 "action-active" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 1103 } 1104
1105 - def __init__(self, 1106 content="", 1107 action_button=None, 1108 background_color = ui_theme.get_alpha_color("text_entry_background"), 1109 acme_color = ui_theme.get_alpha_color("text_entry_acme"), 1110 point_color = ui_theme.get_alpha_color("text_entry_point"), 1111 frame_point_color = ui_theme.get_alpha_color("text_entry_frame_point"), 1112 frame_color = ui_theme.get_alpha_color("text_entry_frame"), 1113 ):
1114 ''' 1115 1116 Initialize InputEntry class. 1117 1118 @param content: Initialize entry text, default is \"\". 1119 @param action_button: Extra button add at right side of input entry, default is None. 1120 @param background_color: Color of input entry background. 1121 @param acme_color: Acme point color of input entry. 1122 @param point_color: Pointer color of input entry. 1123 @param frame_point_color: Frame pointer color of input entry. 1124 @param frame_color: Frame color of input entry. 1125 ''' 1126 # Init. 1127 gtk.VBox.__init__(self) 1128 self.align = gtk.Alignment() 1129 self.align.set(0.5, 0.5, 1.0, 1.0) 1130 self.action_button = action_button 1131 self.h_box = gtk.HBox() 1132 self.entry = Entry(content) 1133 self.background_color = background_color 1134 self.acme_color = acme_color 1135 self.point_color = point_color 1136 self.frame_point_color = frame_point_color 1137 self.frame_color = frame_color 1138 1139 self.pack_start(self.align, False, False) 1140 self.align.add(self.h_box) 1141 self.h_box.pack_start(self.entry) 1142 if action_button: 1143 self.action_align = gtk.Alignment() 1144 self.action_align.set(0.0, 0.5, 0, 0) 1145 self.action_align.set_padding(0, 0, 0, self.entry.padding_x) 1146 self.action_align.add(self.action_button) 1147 1148 self.h_box.pack_start(self.action_align, False, False) 1149 1150 self.action_button.connect("clicked", lambda w: self.emit_action_active_signal()) 1151 1152 # Handle signal. 1153 self.align.connect("expose-event", self.expose_input_entry)
1154
1155 - def set_sensitive(self, sensitive):
1156 ''' 1157 Internal function to wrap function `set_sensitive`. 1158 ''' 1159 super(InputEntry, self).set_sensitive(sensitive) 1160 self.entry.set_sensitive(sensitive)
1161
1162 - def emit_action_active_signal(self):
1163 ''' 1164 Internal callback for `action-active` signal. 1165 ''' 1166 self.emit("action-active", self.get_text())
1167
1168 - def expose_input_entry(self, widget, event):
1169 ''' 1170 Internal callback for `expose-event` signal. 1171 ''' 1172 # Init. 1173 cr = widget.window.cairo_create() 1174 rect = widget.allocation 1175 x, y, w, h = rect.x, rect.y, rect.width, rect.height 1176 1177 # Draw frame. 1178 with cairo_disable_antialias(cr): 1179 cr.set_line_width(1) 1180 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color())) 1181 cr.rectangle(rect.x, rect.y, rect.width, rect.height) 1182 cr.stroke() 1183 1184 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9))) 1185 cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1) 1186 cr.fill() 1187 1188 propagate_expose(widget, event) 1189 1190 return True
1191
1192 - def set_size(self, width, height):
1193 ''' 1194 Set input entry size with given value. 1195 1196 @param width: New width of input entry. 1197 @param height: New height of input entry. 1198 ''' 1199 self.set_size_request(width, height) 1200 1201 action_button_width = 0 1202 if self.action_button: 1203 action_button_width = self.action_button.get_size_request()[-1] + self.entry.padding_x 1204 1205 self.entry.set_size_request(width - 2 - action_button_width, height - 2)
1206
1207 - def set_editable(self, editable):
1208 ''' 1209 Set editable status of input entry. 1210 1211 @param editable: input entry can editable if option is True, else can't edit. 1212 ''' 1213 self.entry.set_editable(editable)
1214
1215 - def set_text(self, text):
1216 ''' 1217 Set text of input entry. 1218 1219 @param text: input entry string. 1220 ''' 1221 self.entry.set_text(text)
1222
1223 - def get_text(self):
1224 ''' 1225 Get text of input entry. 1226 1227 @return: Return text of input entry. 1228 ''' 1229 return self.entry.get_text()
1230
1231 - def focus_input(self):
1232 ''' 1233 Focus input cursor. 1234 ''' 1235 self.entry.grab_focus()
1236 1237 gobject.type_register(InputEntry)
1238 1239 -class ShortcutKeyEntry(gtk.VBox):
1240 ''' 1241 Shortcut key entry. 1242 1243 @undocumented: set_sensitive 1244 @undocumented: emit_action_active_signal 1245 @undocumented: expose_shortcutkey_entry 1246 @undocumented: handle_focus_out 1247 @undocumented: handle_key_press 1248 ''' 1249 1250 __gsignals__ = { 1251 "action-active" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 1252 "wait-key-input" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 1253 "shortcut-key-change" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str,)), 1254 } 1255
1256 - def __init__(self, 1257 content="", 1258 action_button=None, 1259 background_color = ui_theme.get_alpha_color("text_entry_background"), 1260 acme_color = ui_theme.get_alpha_color("text_entry_acme"), 1261 point_color = ui_theme.get_alpha_color("text_entry_point"), 1262 frame_point_color = ui_theme.get_alpha_color("text_entry_frame_point"), 1263 frame_color = ui_theme.get_alpha_color("text_entry_frame"), 1264 ):
1265 ''' 1266 Initialize ShortcutKeyEntry class. 1267 1268 @param content: Initialize entry text, default is \"\". 1269 @param action_button: Extra button add at right side of shortcutkey entry, default is None. 1270 @param background_color: Color of shortcutkey entry background. 1271 @param acme_color: Acme point color of shortcutkey entry. 1272 @param point_color: Pointer color of shortcutkey entry. 1273 @param frame_point_color: Frame pointer color of shortcutkey entry. 1274 @param frame_color: Frame color of shortcutkey entry. 1275 ''' 1276 # Init. 1277 gtk.VBox.__init__(self) 1278 self.align = gtk.Alignment() 1279 self.align.set(0.5, 0.5, 1.0, 1.0) 1280 self.action_button = action_button 1281 self.h_box = gtk.HBox() 1282 self.entry = Entry(content) 1283 self.background_color = background_color 1284 self.acme_color = acme_color 1285 self.point_color = point_color 1286 self.frame_point_color = frame_point_color 1287 self.frame_color = frame_color 1288 1289 self.pack_start(self.align, False, False) 1290 self.align.add(self.h_box) 1291 self.h_box.pack_start(self.entry) 1292 if action_button: 1293 self.action_align = gtk.Alignment() 1294 self.action_align.set(0.0, 0.5, 0, 0) 1295 self.action_align.set_padding(0, 0, 0, self.entry.padding_x) 1296 self.action_align.add(self.action_button) 1297 1298 self.h_box.pack_start(self.action_align) 1299 1300 self.action_button.connect("clicked", lambda w: self.emit_action_active_signal()) 1301 1302 # Handle signal. 1303 self.align.connect("expose-event", self.expose_shortcutkey_entry) 1304 1305 # Setup flags. 1306 self.entry.cursor_visible_flag = False 1307 self.entry.right_menu_visible_flag = False 1308 self.entry.select_area_visible_flag = False 1309 self.entry.editable_flag = False 1310 1311 # Overwrite entry's function. 1312 self.entry.handle_button_press = self.handle_button_press 1313 self.entry.handle_focus_out = self.handle_focus_out 1314 self.entry.handle_key_press = self.handle_key_press 1315 1316 self.shortcut_key = content 1317 self.shortcut_key_record = None
1318
1319 - def set_sensitive(self, sensitive):
1320 ''' 1321 Internal function to wrap function `set_sensitive`. 1322 ''' 1323 super(ShortcutKeyEntry, self).set_sensitive(sensitive) 1324 self.entry.set_sensitive(sensitive)
1325
1326 - def handle_button_press(self, widget, event):
1327 ''' 1328 Internal callback for `action-active` signal. 1329 ''' 1330 # Get input focus. 1331 self.entry.grab_focus() 1332 self.shortcut_key_record = self.shortcut_key 1333 1334 if is_left_button(event): 1335 self.entry.editable_flag = True 1336 self.emit("wait-key-input", self.shortcut_key) 1337 self.set_text(_("Please input new shortcuts")) 1338 self.entry.editable_flag = False 1339 1340 self.entry.queue_draw()
1341
1342 - def handle_focus_out(self, widget, event):
1343 ''' 1344 Internal function to handle focus out. 1345 ''' 1346 if self.shortcut_key != None: 1347 self.entry.editable_flag = True 1348 self.set_text(self.shortcut_key) 1349 self.entry.editable_flag = False 1350 1351 self.entry.grab_focus_flag = False 1352 self.entry.im.focus_out() 1353 self.entry.queue_draw() 1354 1355 if self.shortcut_key != self.shortcut_key_record: 1356 self.emit("shortcut-key-change", self.shortcut_key) 1357 self.shortcut_key_record = None
1358
1359 - def handle_key_press(self, widget, event):
1360 ''' 1361 Internal function to handle key press. 1362 ''' 1363 keyname = get_keyevent_name(event) 1364 if keyname != "": 1365 if keyname == "BackSpace": 1366 self.set_shortcut_key(None) 1367 elif keyname != "": 1368 self.set_shortcut_key(keyname)
1369
1370 - def set_shortcut_key(self, shortcut_key):
1371 ''' 1372 Set shortcut key. 1373 1374 @param shortcut_key: Key string that return by function `dtk.ui.keymap.get_keyevent_name`. 1375 ''' 1376 self.shortcut_key = shortcut_key 1377 1378 self.entry.editable_flag = True 1379 if self.shortcut_key == None: 1380 self.set_text(_("Disabled")) 1381 else: 1382 self.set_text(self.shortcut_key) 1383 self.entry.editable_flag = False
1384
1385 - def get_shortcut_key(self):
1386 ''' 1387 Get shortcut key. 1388 1389 @return: Return shortcut key string, string format look function `dtk.ui.keymap.get_keyevent_name`. 1390 ''' 1391 return self.shortcut_key
1392
1393 - def emit_action_active_signal(self):
1394 ''' 1395 Internal callback for `action-active` signal. 1396 ''' 1397 self.emit("action-active", self.get_text())
1398
1399 - def expose_shortcutkey_entry(self, widget, event):
1400 ''' 1401 Internal callback for `expose-event` signal. 1402 ''' 1403 # Init. 1404 cr = widget.window.cairo_create() 1405 rect = widget.allocation 1406 x, y, w, h = rect.x, rect.y, rect.width, rect.height 1407 1408 # Draw frame. 1409 with cairo_disable_antialias(cr): 1410 cr.set_line_width(1) 1411 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color())) 1412 cr.rectangle(rect.x, rect.y, rect.width, rect.height) 1413 cr.stroke() 1414 1415 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9))) 1416 cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1) 1417 cr.fill() 1418 1419 propagate_expose(widget, event) 1420 1421 return True
1422
1423 - def set_size(self, width, height):
1424 ''' 1425 Set shortcutkey entry size with given value. 1426 1427 @param width: New width of shortcutkey entry. 1428 @param height: New height of shortcutkey entry. 1429 ''' 1430 self.set_size_request(width, height) 1431 1432 action_button_width = 0 1433 if self.action_button: 1434 action_button_width = self.action_button.get_size_request()[-1] + self.entry.padding_x 1435 1436 self.entry.set_size_request(width - 2 - action_button_width, height - 2)
1437
1438 - def set_editable(self, editable):
1439 ''' 1440 Set editable status of shortcutkey entry. 1441 1442 @param editable: shortcutkey entry can editable if option is True, else can't edit. 1443 ''' 1444 self.entry.set_editable(editable)
1445
1446 - def set_text(self, text):
1447 ''' 1448 Set text of shortcutkey entry. 1449 1450 @param text: shortcutkey entry string. 1451 ''' 1452 self.entry.set_text(text)
1453
1454 - def get_text(self):
1455 ''' 1456 Get text of shortcutkey entry. 1457 1458 @return: Return text of shortcutkey entry. 1459 ''' 1460 return self.entry.get_text()
1461
1462 - def focus_input(self):
1463 ''' 1464 Focus input cursor. 1465 ''' 1466 self.entry.grab_focus()
1467 1468 gobject.type_register(ShortcutKeyEntry) 1469 1470 if __name__ == "__main__": 1471 window = gtk.Window() 1472 window.set_colormap(gtk.gdk.Screen().get_rgba_colormap()) 1473 window.set_decorated(False) 1474 window.add_events(gtk.gdk.ALL_EVENTS_MASK) 1475 window.connect("destroy", lambda w: gtk.main_quit()) 1476 window.set_size_request(300, -1) 1477 window.move(100, 100) 1478 1479 entry = Entry("Enter to search") 1480 window.add(entry) 1481 1482 window.show_all() 1483 1484 gtk.main() 1485