Package dtk :: Package ui :: Module skin

Source Code for Module dtk.ui.skin

   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 button import Button, ImageButton, ToggleButton, ActionButton 
  24  from cache_pixbuf import CachePixbuf 
  25  from config import Config 
  26  from constant import SHADE_SIZE, COLOR_SEQUENCE 
  27  from dialog import ConfirmDialog, OpenFileDialog, SaveFileDialog 
  28  from dialog import DialogBox, DIALOG_MASK_SINGLE_PAGE 
  29  from dominant_color import get_dominant_color 
  30  from draw import draw_pixbuf, draw_vlinear, draw_hlinear 
  31  from iconview import IconView 
  32  from label import Label 
  33  from locales import _ 
  34  from scrolled_window import ScrolledWindow 
  35  from skin_config import skin_config 
  36  from theme import ui_theme 
  37  from threads import post_gui 
  38  import tooltip as Tooltip 
  39  import gobject 
  40  import gtk 
  41  import math 
  42  import os 
  43  import shutil 
  44  import tarfile 
  45  import threading as td 
  46  import urllib 
  47  import uuid 
  48  from utils import (is_in_rect, set_cursor, remove_timeout_id, 
  49                     color_hex_to_cairo, cairo_state, container_remove_all,  
  50                     cairo_disable_antialias, remove_directory, end_with_suffixs,  
  51                     create_directory, touch_file, scroll_to_bottom,  
  52                     place_center, get_pixbuf_support_foramts, find_similar_color,  
  53                     get_optimum_pixbuf_from_file) 
  54   
  55  __all__ = ["SkinWindow"] 
56 57 -class LoadSkinThread(td.Thread):
58 ''' 59 Thread to load skin. 60 ''' 61
62 - def __init__(self, 63 skin_dirs, 64 add_skin_icon, 65 add_add_icon):
66 ''' 67 Initialize LoadSkinThread class. 68 69 @param skin_dirs: Skin directories. 70 @param add_skin_icon: Callback to add skin icon. 71 @param add_add_icon: Callback to add add icon. 72 ''' 73 td.Thread.__init__(self) 74 self.setDaemon(True) # make thread exit when main program exit 75 76 self.skin_dirs = skin_dirs 77 self.add_skin_icon = add_skin_icon 78 self.add_add_icon = add_add_icon
79
80 - def run(self):
81 ''' 82 Run. 83 ''' 84 support_foramts = get_pixbuf_support_foramts() 85 for skin_dir in self.skin_dirs: 86 for root, dirs, files in os.walk(skin_dir): 87 dirs.sort() # sort directory with alpha order 88 for filename in files: 89 if end_with_suffixs(filename, support_foramts): 90 self.add_skin_icon(root, filename) 91 92 self.add_add_icon()
93
94 -class SkinWindow(DialogBox):
95 ''' 96 SkinWindow. 97 98 @undocumented: change_skin 99 @undocumented: switch_preview_page 100 @undocumented: switch_edit_page 101 ''' 102
103 - def __init__(self, 104 app_frame_pixbuf, 105 preview_width=450, 106 preview_height=500):
107 ''' 108 Initialize SkinWindow class. 109 110 @param app_frame_pixbuf: Application's pixbuf for frame. 111 @param preview_width: Preview width, default is 450. 112 @param preview_height: Preview height, default is 500. 113 ''' 114 DialogBox.__init__(self, _("Select skin"), preview_width, preview_height, mask_type=DIALOG_MASK_SINGLE_PAGE) 115 self.app_frame_pixbuf = app_frame_pixbuf 116 117 self.preview_page = SkinPreviewPage(self, self.change_skin, self.switch_edit_page) 118 119 self.close_button = Button(_("Close")) 120 self.close_button.connect("clicked", lambda w: w.get_toplevel().destroy()) 121 self.right_button_box.set_buttons([self.close_button]) 122 123 self.switch_preview_page()
124
125 - def change_skin(self, item):
126 ''' 127 Internal function to change skin with given item. 128 ''' 129 # Load skin. 130 if skin_config.reload_skin(os.path.basename(item.skin_dir)): 131 skin_config.apply_skin()
132
133 - def switch_preview_page(self):
134 ''' 135 Internal function to switch preview page. 136 ''' 137 container_remove_all(self.body_box) 138 self.body_box.add(self.preview_page) 139 self.preview_page.highlight_skin() 140 141 self.close_button = Button(_("Close")) 142 self.close_button.connect("clicked", lambda w: w.get_toplevel().destroy()) 143 self.right_button_box.set_buttons([self.close_button]) 144 145 self.show_all()
146
147 - def switch_edit_page(self):
148 ''' 149 Internal function to switch edit page. 150 ''' 151 # Switch to edit page. 152 container_remove_all(self.body_box) 153 edit_page = SkinEditPage(self, self.app_frame_pixbuf, self.switch_preview_page) 154 self.body_box.add(edit_page) 155 156 self.show_all()
157 158 gobject.type_register(SkinWindow)
159 160 -class SkinPreviewPage(gtk.VBox):
161 '''Skin preview.''' 162
163 - def __init__(self, 164 dialog, 165 change_skin_callback, 166 switch_edit_page_callback):
167 '''Init skin preview.''' 168 gtk.VBox.__init__(self) 169 self.dialog = dialog 170 self.change_skin_callback = change_skin_callback 171 self.switch_edit_page_callback = switch_edit_page_callback 172 173 self.preview_align = gtk.Alignment() 174 self.preview_align.set(0.5, 0.5, 1, 1) 175 self.preview_align.set_padding(0, 0, 10, 2) 176 self.preview_scrolled_window = ScrolledWindow() 177 self.preview_scrolled_window.draw_mask = self.dialog.get_mask_func(self.preview_scrolled_window) 178 self.preview_view = IconView() 179 self.preview_view.draw_mask = self.dialog.get_mask_func(self.preview_view) 180 181 self.preview_align.add(self.preview_scrolled_window) 182 self.preview_scrolled_window.add_child(self.preview_view) 183 self.pack_start(self.preview_align, True, True) 184 185 LoadSkinThread([skin_config.system_skin_dir, skin_config.user_skin_dir], 186 self.add_skin_icon, 187 self.add_add_icon).start() 188 189 # Add drag image support. 190 self.drag_dest_set( 191 gtk.DEST_DEFAULT_MOTION | 192 gtk.DEST_DEFAULT_DROP, 193 [("text/uri-list", 0, 1)], 194 gtk.gdk.ACTION_COPY) 195 196 self.connect("drag-data-received", self.drag_skin_file)
197 198 @post_gui
199 - def add_skin_icon(self, root, filename):
200 '''Add skin icon.''' 201 self.preview_view.add_items([SkinPreviewIcon( 202 root, 203 filename, 204 self.change_skin_callback, 205 self.switch_edit_page_callback, 206 self.pop_delete_skin_dialog)])
207 208 @post_gui
209 - def add_add_icon(self):
210 '''Add add icon.''' 211 self.preview_view.add_items([SkinAddIcon(self.create_skin_from_file)])
212
213 - def drag_skin_file(self, widget, drag_context, x, y, selection_data, info, timestamp):
214 '''Drag skin file.''' 215 self.create_skin_from_file(urllib.unquote(selection_data.get_uris()[0].split("file://")[1]))
216
217 - def create_skin_from_file(self, skin_file):
218 '''Create skin from file.''' 219 support_foramts = get_pixbuf_support_foramts() 220 if end_with_suffixs(skin_file, support_foramts): 221 self.create_skin_from_image(skin_file) 222 elif end_with_suffixs(skin_file, ["tar.gz"]): 223 self.create_skin_from_package(skin_file)
224
225 - def create_skin_from_image(self, filepath):
226 '''Create skin from image.''' 227 # Init. 228 skin_dir = os.path.join(skin_config.user_skin_dir, str(uuid.uuid4())) 229 skin_image_file = os.path.basename(filepath) 230 config_file = os.path.join(skin_dir, "config.ini") 231 dominant_color = get_dominant_color(filepath) 232 similar_color = find_similar_color(dominant_color)[0] 233 default_config = [ 234 ("theme", [("theme_name", similar_color)]), 235 ("application", [("app_id", skin_config.app_given_id), 236 ("app_version", skin_config.app_given_version)]), 237 ("background", [("image", skin_image_file), 238 ("x", "0"), 239 ("y", "0"), 240 ("scale_x", "1.0"), 241 ("scale_y", "1.0"), 242 ("dominant_color", dominant_color)]), 243 ("action", [("deletable", "True"), 244 ("editable", "True"), 245 ("vertical_mirror", "False"), 246 ("horizontal_mirror", "False")])] 247 248 # Create skin directory. 249 create_directory(skin_dir, True) 250 251 # Copy skin image file. 252 shutil.copy(filepath, skin_dir) 253 254 # Touch skin config file. 255 touch_file(config_file) 256 257 # Write default skin config information. 258 Config(config_file, default_config).write() 259 260 # Apply new skin. 261 self.preview_view.add_items([SkinPreviewIcon( 262 skin_dir, 263 skin_image_file, 264 self.change_skin_callback, 265 self.switch_edit_page_callback, 266 self.pop_delete_skin_dialog 267 )], -1) 268 if skin_config.reload_skin(os.path.basename(skin_dir)): 269 skin_config.apply_skin() 270 271 self.highlight_skin() 272 273 # Scroll scrollbar to bottom. 274 scroll_to_bottom(self.preview_scrolled_window)
275
276 - def create_skin_from_package(self, filepath):
277 '''Create skin from package.''' 278 # Init. 279 skin_dir = os.path.join(skin_config.user_skin_dir, str(uuid.uuid4())) 280 281 # Create skin directory. 282 create_directory(skin_dir, True) 283 284 # Extract skin package. 285 tar = tarfile.open(filepath, "r:gz") 286 tar.extractall(skin_dir) 287 288 # Get skin image file. 289 config = Config(os.path.join(skin_dir, "config.ini")) 290 config.load() 291 292 # Move theme files to given directory if theme is not in default theme list. 293 skin_theme_name = config.get("theme", "theme_name") 294 if not skin_theme_name in COLOR_SEQUENCE: 295 # Check version when package have special theme that not include in standard themes. 296 app_id = config.get("application", "app_id") 297 app_version = config.get("application", "app_version") 298 if app_id == skin_config.app_given_id and app_version == skin_config.app_given_version: 299 # Remove same theme from given directories. 300 remove_directory(os.path.join(skin_config.ui_theme_dir, skin_theme_name)) 301 remove_directory(os.path.join(skin_config.app_theme_dir, skin_theme_name)) 302 303 # Move new theme files to given directories. 304 shutil.move(os.path.join(skin_dir, "ui_theme", skin_theme_name), skin_config.ui_theme_dir) 305 shutil.move(os.path.join(skin_dir, "app_theme", skin_theme_name), skin_config.app_theme_dir) 306 307 # Remove temp theme directories under skin directory. 308 remove_directory(os.path.join(skin_dir, "ui_theme")) 309 remove_directory(os.path.join(skin_dir, "app_theme")) 310 else: 311 # Remove skin directory if version mismatch. 312 remove_directory(skin_dir) 313 314 ConfirmDialog(_("Skin version mismatch"), 315 _("Import skin version is mismatch with current one!")).show_all() 316 return 317 318 # Apply new skin. 319 skin_image_file = config.get("background", "image") 320 self.preview_view.add_items([SkinPreviewIcon( 321 skin_dir, 322 skin_image_file, 323 self.change_skin_callback, 324 self.switch_edit_page_callback, 325 self.pop_delete_skin_dialog 326 )], -1) 327 if skin_config.reload_skin(os.path.basename(skin_dir)): 328 skin_config.apply_skin() 329 330 self.highlight_skin() 331 332 # Scroll scrollbar to bottom. 333 scroll_to_bottom(self.preview_scrolled_window)
334
335 - def highlight_skin(self):
336 '''Highlight skin.''' 337 # Highlight skin. 338 for item in self.preview_view.items: 339 if isinstance(item, SkinPreviewIcon) and item.skin_dir == skin_config.skin_dir: 340 self.preview_view.clear_highlight() 341 self.preview_view.set_highlight(item) 342 break
343
344 - def pop_delete_skin_dialog(self, item):
345 '''Pop delete skin dialog.''' 346 dialog = ConfirmDialog( 347 _("Delete skin"), 348 _("Are you sure delete this skin?"), 349 confirm_callback = lambda : self.remove_skin(item)) 350 dialog.show_all() 351 dialog.connect("show", lambda w: place_center(self.get_toplevel(), w))
352
353 - def remove_skin(self, item):
354 '''Remove skin.''' 355 if len(self.preview_view.items) > 1: 356 # Change to first theme if delete current theme. 357 if item.skin_dir == skin_config.skin_dir: 358 item_index = max(self.preview_view.items.index(item) - 1, 0) 359 if skin_config.reload_skin(os.path.basename(self.preview_view.items[item_index].skin_dir)): 360 skin_config.apply_skin() 361 self.highlight_skin() 362 363 # Remove skin directory. 364 remove_directory(item.skin_dir) 365 366 # Remove item from icon view. 367 self.preview_view.delete_items([item]) 368 else: 369 print "You can't delete last skin to make application can't use any skin! :)"
370 371 gobject.type_register(SkinPreviewPage)
372 373 -class SkinPreviewIcon(gobject.GObject):
374 '''Icon item.''' 375 376 BUTTON_HIDE = 0 377 BUTTON_NORMAL = 1 378 BUTTON_HOVER = 2 379 380 __gsignals__ = { 381 "redraw-request" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 382 } 383
384 - def __init__(self, 385 skin_dir, 386 background_file, 387 change_skin_callback, 388 switch_edit_page_callback, 389 pop_delete_skin_dialog_callback):
390 '''Init item icon.''' 391 gobject.GObject.__init__(self) 392 self.skin_dir = skin_dir 393 self.background_file = background_file 394 self.change_skin_callback = change_skin_callback 395 self.switch_edit_page_callback = switch_edit_page_callback 396 self.pop_delete_skin_dialog_callback = pop_delete_skin_dialog_callback 397 self.background_path = os.path.join(skin_dir, background_file) 398 self.width = 86 399 self.height = 56 400 self.icon_padding = 2 401 self.padding_x = 7 402 self.padding_y = 10 403 self.hover_flag = False 404 self.highlight_flag = False 405 self.delete_button_status = self.BUTTON_HIDE 406 self.edit_button_status = self.BUTTON_HIDE 407 408 self.pixbuf = get_optimum_pixbuf_from_file(self.background_path, self.width, self.height, False) 409 410 self.show_delete_button_id = None 411 self.show_edit_button_id = None 412 self.show_delay = 500 # milliseconds 413 414 # Load skin config information. 415 self.config = Config(os.path.join(self.skin_dir, "config.ini")) 416 self.config.load()
417
418 - def is_in_delete_button_area(self, x, y):
419 '''Is cursor in delete button area.''' 420 delete_pixbuf = ui_theme.get_pixbuf("skin/delete_normal.png").get_pixbuf() 421 422 return is_in_rect((x, y), 423 (self.get_width() - delete_pixbuf.get_width() - (self.icon_padding + self.padding_x) - 3, 424 (self.icon_padding + self.padding_x) + 4, 425 delete_pixbuf.get_width(), 426 delete_pixbuf.get_height()))
427
428 - def is_in_edit_button_area(self, x, y):
429 '''Is cursor in edit button area.''' 430 edit_pixbuf = ui_theme.get_pixbuf("skin/edit_normal.png").get_pixbuf() 431 432 return is_in_rect((x, y), 433 (self.get_width() - edit_pixbuf.get_width() - (self.icon_padding + self.padding_x) - 3, 434 self.get_height() - edit_pixbuf.get_height() - (self.icon_padding + self.padding_x) - 4, 435 edit_pixbuf.get_width(), 436 edit_pixbuf.get_height()))
437
438 - def is_deletable(self):
439 '''Is deletable.''' 440 return self.config.getboolean("action", "deletable")
441
442 - def is_editable(self):
443 '''Is editable.''' 444 return self.config.getboolean("action", "editable")
445
446 - def emit_redraw_request(self):
447 '''Emit redraw-request signal.''' 448 self.emit("redraw-request")
449
450 - def get_width(self):
451 '''Get width.''' 452 return self.width + (self.icon_padding + self.padding_x) * 2
453
454 - def get_height(self):
455 '''Get height.''' 456 return self.height + (self.icon_padding + self.padding_y) * 2
457
458 - def render(self, cr, rect):
459 '''Render item.''' 460 # Draw frame. 461 if self.hover_flag: 462 pixbuf = ui_theme.get_pixbuf("skin/preview_hover.png").get_pixbuf() 463 elif self.highlight_flag: 464 pixbuf = ui_theme.get_pixbuf("skin/preview_highlight.png").get_pixbuf() 465 else: 466 pixbuf = ui_theme.get_pixbuf("skin/preview_normal.png").get_pixbuf() 467 draw_pixbuf( 468 cr, 469 pixbuf, 470 rect.x + self.padding_x, 471 rect.y + self.padding_y) 472 473 # Draw background. 474 with cairo_state(cr): 475 # Mirror image if necessarily. 476 preview_config = Config(os.path.join(self.skin_dir, "config.ini")) 477 preview_config.load() 478 479 pixbuf = self.pixbuf.copy() 480 if preview_config.getboolean("action", "vertical_mirror"): 481 pixbuf = pixbuf.flip(True) 482 483 if preview_config.getboolean("action", "horizontal_mirror"): 484 pixbuf = pixbuf.flip(False) 485 486 # Draw cover. 487 draw_pixbuf( 488 cr, 489 pixbuf, 490 rect.x + (rect.width - self.pixbuf.get_width()) / 2, 491 rect.y + (rect.height - self.pixbuf.get_height()) / 2 492 ) 493 494 # Draw delete button. 495 if self.delete_button_status != self.BUTTON_HIDE: 496 if self.delete_button_status == self.BUTTON_NORMAL: 497 pixbuf = ui_theme.get_pixbuf("skin/delete_normal.png").get_pixbuf() 498 elif self.delete_button_status == self.BUTTON_HOVER: 499 pixbuf = ui_theme.get_pixbuf("skin/delete_hover.png").get_pixbuf() 500 501 delete_button_x = rect.x + rect.width - pixbuf.get_width() - (self.icon_padding + self.padding_x) - 3 502 delete_button_y = rect.y + (self.icon_padding + self.padding_x) + 4 503 504 draw_pixbuf(cr, pixbuf, delete_button_x, delete_button_y) 505 506 # Draw edit button. 507 if self.edit_button_status != self.BUTTON_HIDE: 508 if self.edit_button_status == self.BUTTON_NORMAL: 509 pixbuf = ui_theme.get_pixbuf("skin/edit_normal.png").get_pixbuf() 510 elif self.edit_button_status == self.BUTTON_HOVER: 511 pixbuf = ui_theme.get_pixbuf("skin/edit_hover.png").get_pixbuf() 512 513 edit_button_x = rect.x + rect.width - pixbuf.get_width() - (self.icon_padding + self.padding_x) - 3 514 edit_button_y = rect.y + rect.height - pixbuf.get_height() - (self.icon_padding + self.padding_x) - 4 515 516 draw_pixbuf(cr, pixbuf, edit_button_x, edit_button_y)
517
518 - def icon_item_motion_notify(self, x, y):
519 '''Handle `motion-notify-event` signal.''' 520 self.hover_flag = True 521 522 remove_timeout_id(self.show_delete_button_id) 523 remove_timeout_id(self.show_edit_button_id) 524 525 if self.is_deletable(): 526 if self.is_in_delete_button_area(x, y): 527 if self.delete_button_status == self.BUTTON_HIDE: 528 self.show_delete_button_id = gtk.timeout_add(self.show_delay, lambda : self.show_delete_button(self.BUTTON_HOVER)) 529 else: 530 self.delete_button_status = self.BUTTON_HOVER 531 else: 532 if self.delete_button_status == self.BUTTON_HOVER: 533 self.delete_button_status = self.BUTTON_NORMAL 534 else: 535 self.show_delete_button_id = gtk.timeout_add(self.show_delay, lambda : self.show_delete_button(self.BUTTON_NORMAL)) 536 else: 537 self.delete_button_status = self.BUTTON_HIDE 538 539 if self.is_editable(): 540 if self.is_in_edit_button_area(x, y): 541 if self.edit_button_status == self.BUTTON_HIDE: 542 self.show_edit_button_id = gtk.timeout_add(self.show_delay, lambda : self.show_edit_button(self.BUTTON_HOVER)) 543 else: 544 self.edit_button_status = self.BUTTON_HOVER 545 else: 546 if self.edit_button_status == self.BUTTON_HOVER: 547 self.edit_button_status = self.BUTTON_NORMAL 548 else: 549 self.show_edit_button_id = gtk.timeout_add(self.show_delay, lambda : self.show_edit_button(self.BUTTON_NORMAL)) 550 else: 551 self.edit_button_status = self.BUTTON_HIDE 552 553 self.emit_redraw_request()
554
555 - def show_delete_button(self, status):
556 '''Show delete button.''' 557 self.delete_button_status = status 558 self.emit_redraw_request()
559
560 - def show_edit_button(self, status):
561 '''Show edit button.''' 562 self.edit_button_status = status 563 self.emit_redraw_request()
564
565 - def icon_item_lost_focus(self):
566 '''Lost focus.''' 567 self.hover_flag = False 568 self.delete_button_status = self.BUTTON_HIDE 569 self.edit_button_status = self.BUTTON_HIDE 570 571 remove_timeout_id(self.show_delete_button_id) 572 remove_timeout_id(self.show_edit_button_id) 573 574 self.emit_redraw_request()
575
576 - def icon_item_highlight(self):
577 '''Highlight item.''' 578 self.highlight_flag = True 579 580 self.emit_redraw_request()
581
582 - def icon_item_normal(self):
583 '''Set item with normal status.''' 584 self.highlight_flag = False 585 586 self.emit_redraw_request()
587
588 - def icon_item_button_press(self, x, y):
589 '''Handle button-press event.''' 590 if not self.is_deletable() and not self.is_editable(): 591 self.change_skin_callback(self) 592 else: 593 if self.is_deletable() and self.is_in_delete_button_area(x, y): 594 if self.delete_button_status != self.BUTTON_HIDE: 595 self.delete_button_status = self.BUTTON_HIDE 596 self.edit_button_status = self.BUTTON_HIDE 597 598 self.pop_delete_skin_dialog_callback(self) 599 elif self.is_editable() and self.is_in_edit_button_area(x, y): 600 if self.edit_button_status != self.BUTTON_HIDE: 601 self.delete_button_status = self.BUTTON_HIDE 602 self.edit_button_status = self.BUTTON_HIDE 603 604 self.change_skin_callback(self) 605 self.switch_edit_page_callback() 606 else: 607 self.change_skin_callback(self) 608 609 self.emit_redraw_request()
610
611 - def icon_item_button_release(self, x, y):
612 '''Handle button-release event.''' 613 if self.is_deletable(): 614 if self.is_in_delete_button_area(x, y): 615 self.delete_button_status = self.BUTTON_HOVER 616 else: 617 self.delete_button_status = self.BUTTON_NORMAL 618 619 if self.is_editable(): 620 if self.is_in_edit_button_area(x, y): 621 self.edit_button_status = self.BUTTON_HOVER 622 else: 623 self.edit_button_status = self.BUTTON_NORMAL 624 625 self.emit_redraw_request()
626
627 - def icon_item_single_click(self, x, y):
628 '''Handle single click event.''' 629 pass
630
631 - def icon_item_double_click(self, x, y):
632 '''Handle double click event.''' 633 pass
634 635 gobject.type_register(SkinPreviewIcon)
636 637 -class SkinAddIcon(gobject.GObject):
638 '''Icon item.''' 639 640 __gsignals__ = { 641 "redraw-request" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 642 } 643
644 - def __init__(self, ok_callback=None, cancel_callback=None):
645 '''Init item icon.''' 646 gobject.GObject.__init__(self) 647 self.ok_callback = ok_callback 648 self.cancel_callback = cancel_callback 649 self.width = 86 650 self.height = 56 651 self.icon_padding = 2 652 self.padding_x = 7 653 self.padding_y = 10 654 self.hover_flag = False 655 self.highlight_flag = False
656
657 - def emit_redraw_request(self):
658 '''Emit redraw-request signal.''' 659 self.emit("redraw-request")
660
661 - def get_width(self):
662 '''Get width.''' 663 return self.width + (self.icon_padding + self.padding_x) * 2
664
665 - def get_height(self):
666 '''Get height.''' 667 return self.height + (self.icon_padding + self.padding_y) * 2
668
669 - def render(self, cr, rect):
670 '''Render item.''' 671 # Draw frame. 672 if self.hover_flag: 673 pixbuf = ui_theme.get_pixbuf("skin/preview_hover.png").get_pixbuf() 674 elif self.highlight_flag: 675 pixbuf = ui_theme.get_pixbuf("skin/preview_highlight.png").get_pixbuf() 676 else: 677 pixbuf = ui_theme.get_pixbuf("skin/preview_normal.png").get_pixbuf() 678 draw_pixbuf( 679 cr, 680 pixbuf, 681 rect.x + self.padding_x, 682 rect.y + self.padding_y) 683 684 # Draw background. 685 with cairo_state(cr): 686 pixbuf = ui_theme.get_pixbuf("skin/add.png").get_pixbuf() 687 # Draw cover. 688 draw_pixbuf( 689 cr, 690 pixbuf, 691 rect.x + (rect.width - pixbuf.get_width()) / 2, 692 rect.y + (rect.height - pixbuf.get_height()) / 2 693 )
694
695 - def icon_item_motion_notify(self, x, y):
696 '''Handle `motion-notify-event` signal.''' 697 self.hover_flag = True 698 699 self.emit_redraw_request()
700
701 - def icon_item_lost_focus(self):
702 '''Lost focus.''' 703 self.hover_flag = False 704 705 self.emit_redraw_request()
706
707 - def icon_item_highlight(self):
708 '''Highlight item.''' 709 self.highlight_flag = True 710 711 self.emit_redraw_request()
712
713 - def icon_item_normal(self):
714 '''Set item with normal status.''' 715 self.highlight_flag = False 716 717 self.emit_redraw_request()
718
719 - def icon_item_button_press(self, x, y):
720 '''Handle button-press event.''' 721 OpenFileDialog(_("Add skin from file"), None, self.ok_callback, self.cancel_callback)
722
723 - def icon_item_button_release(self, x, y):
724 '''Handle button-release event.''' 725 pass
726
727 - def icon_item_single_click(self, x, y):
728 '''Handle single click event.''' 729 pass
730
731 - def icon_item_double_click(self, x, y):
732 '''Handle double click event.''' 733 pass
734 735 gobject.type_register(SkinAddIcon)
736 737 -class SkinEditPage(gtk.VBox):
738 '''Init skin edit page.''' 739
740 - def __init__(self, 741 dialog, 742 app_frame_pixbuf, 743 switch_preview_page):
744 '''Init skin edit page.''' 745 gtk.VBox.__init__(self) 746 self.dialog = dialog 747 self.switch_preview_page = switch_preview_page 748 self.edit_area_align = gtk.Alignment() 749 self.edit_area_align.set(0.5, 0.5, 1, 1) 750 self.edit_area_align.set_padding(5, 0, 28, 28) 751 self.edit_area = SkinEditArea(app_frame_pixbuf) 752 self.edit_area_align.add(self.edit_area) 753 754 self.action_align = gtk.Alignment() 755 self.action_align.set(0.5, 0.5, 1, 1) 756 self.action_align.set_padding(5, 5, 30, 30) 757 self.action_box = gtk.HBox() 758 self.action_left_align = gtk.Alignment() 759 self.action_left_align.set(0.0, 0.5, 0, 0) 760 self.action_right_align = gtk.Alignment() 761 self.action_right_align.set(1.0, 0.5, 0, 0) 762 self.action_left_box = gtk.HBox() 763 self.action_left_box.set_size_request(-1, 20) 764 self.action_right_box = gtk.HBox() 765 self.action_right_box.set_size_request(-1, 20) 766 self.action_align.add(self.action_box) 767 self.action_box.pack_start(self.action_left_align, True, True) 768 self.action_box.pack_start(self.action_right_align, False, False) 769 self.action_left_align.add(self.action_left_box) 770 self.action_right_align.add(self.action_right_box) 771 772 # Default display auto resize status when image is 1:1 status. 773 if skin_config.scale_x == 1.0 and skin_config.scale_y == 1.0: 774 action_index = 1 775 # Otherwise default display 1:1 status. 776 else: 777 action_index = 0 778 779 self.resize_button = ActionButton( 780 [((ui_theme.get_pixbuf("skin/reset_normal.png"), 781 ui_theme.get_pixbuf("skin/reset_hover.png"), 782 ui_theme.get_pixbuf("skin/reset_press.png")), 783 lambda w: self.edit_area.click_reset_button()), 784 ((ui_theme.get_pixbuf("skin/auto_resize_normal.png"), 785 ui_theme.get_pixbuf("skin/auto_resize_hover.png"), 786 ui_theme.get_pixbuf("skin/auto_resize_press.png")), 787 lambda w: self.edit_area.click_auto_resize_button())], 788 action_index 789 ) 790 self.v_split_button = ImageButton( 791 ui_theme.get_pixbuf("skin/v_split_normal.png"), 792 ui_theme.get_pixbuf("skin/v_split_hover.png"), 793 ui_theme.get_pixbuf("skin/v_split_press.png"), 794 ) 795 self.h_split_button = ImageButton( 796 ui_theme.get_pixbuf("skin/h_split_normal.png"), 797 ui_theme.get_pixbuf("skin/h_split_hover.png"), 798 ui_theme.get_pixbuf("skin/h_split_press.png"), 799 ) 800 self.lock_button = ToggleButton( 801 ui_theme.get_pixbuf("skin/lock_normal.png"), 802 ui_theme.get_pixbuf("skin/lock_press.png"), 803 ui_theme.get_pixbuf("skin/lock_hover.png"), 804 ui_theme.get_pixbuf("skin/lock_press.png"), 805 ) 806 self.lock_button.connect("toggled", self.edit_area.update_lock_status) 807 self.lock_button.set_active(True) 808 self.action_left_box.pack_start(self.resize_button) 809 self.action_left_box.pack_start(self.v_split_button) 810 self.action_left_box.pack_start(self.h_split_button) 811 self.action_left_box.pack_start(self.lock_button) 812 813 self.export_button = ImageButton( 814 ui_theme.get_pixbuf("skin/export_normal.png"), 815 ui_theme.get_pixbuf("skin/export_hover.png"), 816 ui_theme.get_pixbuf("skin/export_press.png"), 817 ) 818 self.action_right_box.pack_start(self.export_button) 819 820 self.export_button.connect("clicked", self.export_skin) 821 self.v_split_button.connect("clicked", lambda w: self.click_vertical_mirror_button()) 822 self.h_split_button.connect("clicked", lambda w: self.click_horizontal_mirror_button()) 823 824 Tooltip.text(self.resize_button, _("Zoom")) 825 Tooltip.text(self.v_split_button, _("Vertical flip")) 826 Tooltip.text(self.h_split_button, _("Horizontal flip")) 827 Tooltip.text(self.lock_button, _("Lock scaling")) 828 Tooltip.text(self.export_button, _("Export skin")) 829 830 self.color_label_align = gtk.Alignment() 831 self.color_label_align.set(0.0, 0.5, 0, 0) 832 self.color_label_align.set_padding(0, 0, 20, 0) 833 self.color_label = Label(_("Select color"), ui_theme.get_color("skin_title")) 834 self.color_label.set_size_request(100, 30) 835 self.color_label_align.add(self.color_label) 836 837 self.color_select_align = gtk.Alignment() 838 self.color_select_align.set(0.5, 0.5, 1, 1) 839 self.color_select_align.set_padding(0, 0, 30, 30) 840 self.color_select_view = IconView() 841 self.color_select_view.draw_mask = self.dialog.get_mask_func(self.color_select_view) 842 self.color_select_scrolled_window = ScrolledWindow() 843 self.color_select_scrolled_window.add_child(self.color_select_view) 844 self.color_select_align.add(self.color_select_scrolled_window) 845 846 for color in COLOR_SEQUENCE: 847 self.color_select_view.add_items([ColorIconItem(color)]) 848 849 self.back_button = Button(_("Return")) 850 self.back_button.connect("clicked", lambda w: self.switch_preview_page()) 851 self.dialog.right_button_box.set_buttons([self.back_button]) 852 853 self.pack_start(self.edit_area_align, False, False) 854 self.pack_start(self.action_align, False, False) 855 self.pack_start(self.color_label_align, True, True) 856 self.pack_start(self.color_select_align, True, True) 857 858 self.highlight_color_icon(skin_config.theme_name) 859 860 self.color_select_view.connect("button-press-item", self.change_skin_theme)
861
863 '''Click vertical mirror button.''' 864 skin_config.vertical_mirror_background() 865 skin_config.save_skin()
866
868 '''Click horizontal mirror button.''' 869 skin_config.horizontal_mirror_background() 870 skin_config.save_skin()
871
872 - def change_skin_theme(self, view, item, x, y):
873 '''Change skin theme.''' 874 # Highlight theme icon. 875 self.highlight_color_icon(item.color) 876 877 # Change and save theme. 878 skin_config.change_theme(item.color) 879 skin_config.save_skin()
880
881 - def highlight_color_icon(self, color):
882 '''Highlight color icon.''' 883 for item in self.color_select_view.items: 884 if item.color == color: 885 self.color_select_view.clear_highlight() 886 self.color_select_view.set_highlight(item) 887 break
888
889 - def export_skin(self, button):
890 '''Export skin.''' 891 SaveFileDialog(_("Export skin"), None, skin_config.export_skin)
892 893 gobject.type_register(SkinEditPage)
894 895 -class ColorIconItem(gobject.GObject):
896 '''Icon item.''' 897 898 __gsignals__ = { 899 "redraw-request" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), 900 } 901
902 - def __init__(self, color):
903 '''Init item icon.''' 904 gobject.GObject.__init__(self) 905 self.color = color 906 self.width = 42 907 self.height = 27 908 self.padding_x = 6 909 self.padding_y = 6 910 self.hover_flag = False 911 self.highlight_flag = False
912
913 - def emit_redraw_request(self):
914 '''Emit redraw-request signal.''' 915 self.emit("redraw-request")
916
917 - def get_width(self):
918 '''Get width.''' 919 return self.width + self.padding_x * 2
920
921 - def get_height(self):
922 '''Get height.''' 923 return self.height + self.padding_y * 2
924
925 - def render(self, cr, rect):
926 '''Render item.''' 927 # Init. 928 draw_x = rect.x + self.padding_x 929 draw_y = rect.y + self.padding_y 930 931 # Draw color area. 932 draw_pixbuf( 933 cr, 934 ui_theme.get_pixbuf("skin/color_%s.png" % (self.color)).get_pixbuf(), 935 draw_x, 936 draw_y) 937 938 # Draw select effect. 939 if self.hover_flag: 940 draw_pixbuf( 941 cr, 942 ui_theme.get_pixbuf("skin/color_frame_hover.png").get_pixbuf(), 943 draw_x, 944 draw_y) 945 elif self.highlight_flag: 946 draw_pixbuf( 947 cr, 948 ui_theme.get_pixbuf("skin/color_frame_highlight.png").get_pixbuf(), 949 draw_x, 950 draw_y)
951
952 - def icon_item_motion_notify(self, x, y):
953 '''Handle `motion-notify-event` signal.''' 954 self.hover_flag = True 955 956 self.emit_redraw_request()
957
958 - def icon_item_lost_focus(self):
959 '''Lost focus.''' 960 self.hover_flag = False 961 962 self.emit_redraw_request()
963
964 - def icon_item_highlight(self):
965 '''Highlight item.''' 966 self.highlight_flag = True 967 968 self.emit_redraw_request()
969
970 - def icon_item_normal(self):
971 '''Set item with normal status.''' 972 self.highlight_flag = False 973 974 self.emit_redraw_request()
975
976 - def icon_item_button_press(self, x, y):
977 '''Handle button-press event.''' 978 pass
979
980 - def icon_item_button_release(self, x, y):
981 '''Handle button-release event.''' 982 pass
983
984 - def icon_item_single_click(self, x, y):
985 '''Handle single click event.''' 986 pass
987
988 - def icon_item_double_click(self, x, y):
989 '''Handle double click event.''' 990 pass
991 992 gobject.type_register(ColorIconItem)
993 994 -class SkinEditArea(gtk.EventBox):
995 '''Skin edit area.''' 996 997 POSITION_LEFT_SIDE = 0 998 POSITION_RIGHT_SIDE = 1 999 POSITION_TOP_SIDE = 2 1000 POSITION_BOTTOM_SIDE = 3 1001 POSITION_TOP_LEFT_CORNER = 4 1002 POSITION_TOP_RIGHT_CORNER = 5 1003 POSITION_BOTTOM_LEFT_CORNER = 6 1004 POSITION_BOTTOM_RIGHT_CORNER = 7 1005 POSITION_INSIDE = 8 1006 POSITION_OUTSIDE = 9 1007
1008 - def __init__(self, app_frame_pixbuf):
1009 '''Init skin edit area.''' 1010 gtk.EventBox.__init__(self) 1011 self.set_has_window(False) 1012 self.add_events(gtk.gdk.ALL_EVENTS_MASK) 1013 self.set_can_focus(True) # can focus to response key-press signal 1014 1015 self.preview_pixbuf = app_frame_pixbuf.get_pixbuf() 1016 self.preview_frame_width = 390 1017 self.preview_frame_height = 270 1018 self.app_window_width = skin_config.app_window_width 1019 self.app_window_height = skin_config.app_window_height 1020 self.preview_pixbuf_width = self.preview_pixbuf.get_width() 1021 self.preview_pixbuf_height = self.preview_pixbuf.get_height() 1022 self.padding_x = (self.preview_frame_width - self.preview_pixbuf_width) / 2 1023 self.padding_y = (self.preview_frame_height - self.preview_pixbuf_height) / 2 1024 self.set_size_request(self.preview_frame_width, self.preview_frame_height) 1025 1026 # Load config from skin_config. 1027 self.background_pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(skin_config.skin_dir, skin_config.image)) 1028 self.background_preview_width = int(self.eval_scale(self.background_pixbuf.get_width())) 1029 self.background_preview_height = int(self.eval_scale(self.background_pixbuf.get_height())) 1030 self.dominant_color = skin_config.dominant_color 1031 1032 # Update skin config. 1033 self.update_skin_config() 1034 1035 self.resize_pointer_size = 8 1036 self.resize_frame_size = 2 1037 self.shadow_radius = 6 1038 self.frame_radius = 2 1039 self.shadow_padding = self.shadow_radius - self.frame_radius 1040 self.shadow_size = int(self.eval_scale(SHADE_SIZE)) 1041 self.min_resize_width = self.min_resize_height = self.shadow_size 1042 1043 self.drag_start_x = 0 1044 self.drag_start_y = 0 1045 self.drag_background_x = 0 1046 self.drag_background_y = 0 1047 1048 self.action_type = None 1049 self.button_press_flag = False 1050 self.button_release_flag = True 1051 self.resize_frame_flag = False 1052 self.in_resize_area_flag = False 1053 self.lock_flag = True 1054 1055 self.cache_pixbuf = CachePixbuf() 1056 1057 self.connect("expose-event", self.expose_skin_edit_area) 1058 self.connect("button-press-event", self.button_press_skin_edit_area) 1059 self.connect("button-release-event", self.button_release_skin_edit_area) 1060 self.connect("motion-notify-event", self.motion_skin_edit_area) 1061 self.connect("leave-notify-event", self.leave_notify_skin_edit_area)
1062
1063 - def eval_scale(self, value):
1064 '''Eval scale.''' 1065 return value * self.preview_pixbuf_width / self.app_window_width
1066
1067 - def expose_skin_edit_area(self, widget, event):
1068 '''Expose edit area.''' 1069 cr = widget.window.cairo_create() 1070 rect = widget.allocation 1071 x, y, w, h = rect.x, rect.y, rect.width, rect.height 1072 resize_x = int(self.resize_x) 1073 resize_y = int(self.resize_y) 1074 1075 with cairo_state(cr): 1076 cr.rectangle(x, y, w, h) 1077 cr.clip() 1078 1079 cr.set_source_rgb(1, 1, 1) 1080 cr.rectangle(x, y, w, h) 1081 cr.fill() 1082 1083 if self.button_release_flag: 1084 offset_x = x + self.padding_x 1085 offset_y = y + self.padding_y 1086 1087 # Draw dominant color. 1088 cr.set_source_rgb(*color_hex_to_cairo(self.dominant_color)) 1089 cr.rectangle( 1090 offset_x + resize_x, 1091 offset_y + resize_y, 1092 w - self.padding_x - resize_x, 1093 h - self.padding_y - resize_y) 1094 cr.fill() 1095 1096 # Draw background. 1097 self.cache_pixbuf.scale(self.background_pixbuf, self.resize_width, self.resize_height, 1098 skin_config.vertical_mirror, skin_config.horizontal_mirror) 1099 1100 draw_pixbuf( 1101 cr, 1102 self.cache_pixbuf.get_cache(), 1103 x + self.padding_x + resize_x, 1104 y + self.padding_y + resize_y) 1105 1106 # Draw dominant shadow color. 1107 if self.button_release_flag: 1108 offset_x = x + self.padding_x 1109 offset_y = y + self.padding_y 1110 background_area_width = self.resize_width + resize_x 1111 background_area_height = self.resize_height + resize_y 1112 1113 with cairo_state(cr): 1114 cr.rectangle( 1115 x + self.padding_x + resize_x, 1116 y + self.padding_y + resize_y, 1117 w, 1118 h 1119 ) 1120 cr.clip() 1121 1122 draw_hlinear( 1123 cr, 1124 offset_x + background_area_width - self.shadow_size, 1125 offset_y + resize_y, 1126 self.shadow_size, 1127 background_area_height - resize_y, 1128 [(0, (self.dominant_color, 0)), 1129 (1, (self.dominant_color, 1))]) 1130 1131 draw_vlinear( 1132 cr, 1133 offset_x + resize_x, 1134 offset_y + background_area_height - self.shadow_size, 1135 background_area_width - resize_x, 1136 self.shadow_size, 1137 [(0, (self.dominant_color, 0)), 1138 (1, (self.dominant_color, 1))] 1139 ) 1140 1141 # Draw window. 1142 draw_pixbuf( 1143 cr, 1144 self.preview_pixbuf, 1145 x + self.padding_x, 1146 y + self.padding_y) 1147 1148 if self.in_resize_area_flag: 1149 resize_x = x + self.padding_x + resize_x 1150 resize_y = y + self.padding_y + resize_y 1151 1152 # Draw resize frame. 1153 cr.set_source_rgb(0, 1, 1) 1154 1155 # Resize frame. 1156 cr.rectangle( # top 1157 resize_x, 1158 resize_y - self.resize_frame_size / 2, 1159 self.resize_width, 1160 self.resize_frame_size) 1161 cr.rectangle( # bottom 1162 resize_x, 1163 resize_y + self.resize_height - self.resize_frame_size / 2, 1164 self.resize_width, 1165 self.resize_frame_size) 1166 cr.rectangle( # left 1167 resize_x - self.resize_frame_size / 2, 1168 resize_y, 1169 self.resize_frame_size, 1170 self.resize_height) 1171 cr.rectangle( # right 1172 resize_x + self.resize_width - self.resize_frame_size / 2, 1173 resize_y, 1174 self.resize_frame_size, 1175 self.resize_height) 1176 1177 # Resize pointer. 1178 cr.arc( # top-left 1179 resize_x, 1180 resize_y, 1181 self.resize_pointer_size / 2, 1182 0, 1183 2 * math.pi) 1184 cr.fill() 1185 1186 cr.arc( # top-center 1187 resize_x + self.resize_width / 2, 1188 resize_y, 1189 self.resize_pointer_size / 2, 1190 0, 1191 2 * math.pi) 1192 cr.fill() 1193 1194 cr.arc( # top-right 1195 resize_x + self.resize_width, 1196 resize_y, 1197 self.resize_pointer_size / 2, 1198 0, 1199 2 * math.pi) 1200 cr.fill() 1201 1202 cr.arc( # bottom-left 1203 resize_x, 1204 resize_y + self.resize_height, 1205 self.resize_pointer_size / 2, 1206 0, 1207 2 * math.pi) 1208 cr.fill() 1209 1210 cr.arc( # bottom-center 1211 resize_x + self.resize_width / 2, 1212 resize_y + self.resize_height, 1213 self.resize_pointer_size / 2, 1214 0, 1215 2 * math.pi) 1216 cr.fill() 1217 1218 cr.arc( # bottom-right 1219 resize_x + self.resize_width, 1220 resize_y + self.resize_height, 1221 self.resize_pointer_size / 2, 1222 0, 1223 2 * math.pi) 1224 cr.fill() 1225 1226 cr.arc( # left-center 1227 resize_x, 1228 resize_y + self.resize_height / 2, 1229 self.resize_pointer_size / 2, 1230 0, 1231 2 * math.pi) 1232 cr.fill() 1233 1234 cr.arc( # right-center 1235 resize_x + self.resize_width, 1236 resize_y + self.resize_height / 2, 1237 self.resize_pointer_size / 2, 1238 0, 1239 2 * math.pi) 1240 cr.fill() 1241 1242 # Draw preview frame. 1243 with cairo_disable_antialias(cr): 1244 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("skin_edit_area_preview").get_color())) 1245 cr.rectangle(x, y, w, h) 1246 cr.stroke()
1247
1248 - def button_press_skin_edit_area(self, widget, event):
1249 '''Callback for `button-press-event`''' 1250 self.button_press_flag = True 1251 self.button_release_flag = False 1252 self.action_type = self.skin_edit_area_get_action_type(event) 1253 self.skin_edit_area_set_cursor(self.action_type) 1254 1255 self.drag_start_x = event.x 1256 self.drag_start_y = event.y 1257 1258 self.drag_background_x = self.resize_x 1259 self.drag_background_y = self.resize_y
1260
1261 - def button_release_skin_edit_area(self, widget, event):
1262 '''Callback for `button-release-event`.''' 1263 # Init. 1264 rect = widget.allocation 1265 1266 # Update status. 1267 self.button_press_flag = False 1268 self.button_release_flag = True 1269 self.action_type = None 1270 1271 # Update cursor. 1272 if is_in_rect((event.x, event.y), (0, 0, rect.width, rect.height)): 1273 self.skin_edit_area_set_cursor(self.skin_edit_area_get_action_type(event)) 1274 else: 1275 self.skin_edit_area_set_cursor(None) 1276 1277 # Change skin. 1278 skin_config.update_image_size( 1279 self.resize_x * self.background_preview_width * self.app_window_width / self.preview_pixbuf_width / self.resize_width, 1280 self.resize_y * self.background_preview_height * self.app_window_width / self.preview_pixbuf_width / self.resize_height, 1281 self.resize_width / float(self.background_preview_width), 1282 self.resize_height / float(self.background_preview_height) 1283 ) 1284 1285 # Update in_resize_area_flag. 1286 self.in_resize_area_flag = self.is_in_resize_area(event) 1287 1288 # Apply skin. 1289 skin_config.apply_skin() 1290 skin_config.save_skin()
1291
1292 - def leave_notify_skin_edit_area(self, widget, event):
1293 '''Callback for `leave-notify-event` signal.''' 1294 if not self.button_press_flag: 1295 self.in_resize_area_flag = False 1296 1297 set_cursor(self, None) 1298 1299 self.queue_draw()
1300
1301 - def motion_skin_edit_area(self, widget, event):
1302 '''Callback for `motion-notify-event`.''' 1303 if self.button_press_flag: 1304 if self.action_type != None: 1305 if self.action_type == self.POSITION_INSIDE: 1306 self.skin_edit_area_drag_background(event) 1307 elif self.action_type == self.POSITION_TOP_LEFT_CORNER: 1308 self.skin_edit_area_resize(self.action_type, event) 1309 elif self.action_type == self.POSITION_TOP_RIGHT_CORNER: 1310 self.skin_edit_area_resize(self.action_type, event) 1311 elif self.action_type == self.POSITION_BOTTOM_LEFT_CORNER: 1312 self.skin_edit_area_resize(self.action_type, event) 1313 elif self.action_type == self.POSITION_BOTTOM_RIGHT_CORNER: 1314 self.skin_edit_area_resize(self.action_type, event) 1315 elif self.action_type == self.POSITION_TOP_SIDE: 1316 self.skin_edit_area_resize(self.action_type, event) 1317 elif self.action_type == self.POSITION_BOTTOM_SIDE: 1318 self.skin_edit_area_resize(self.action_type, event) 1319 elif self.action_type == self.POSITION_LEFT_SIDE: 1320 self.skin_edit_area_resize(self.action_type, event) 1321 elif self.action_type == self.POSITION_RIGHT_SIDE: 1322 self.skin_edit_area_resize(self.action_type, event) 1323 else: 1324 self.skin_edit_area_set_cursor(self.skin_edit_area_get_action_type(event)) 1325 1326 if not self.button_press_flag: 1327 old_flag = self.in_resize_area_flag 1328 self.in_resize_area_flag = self.is_in_resize_area(event) 1329 if old_flag != self.in_resize_area_flag: 1330 self.queue_draw()
1331
1332 - def skin_edit_area_set_cursor(self, action_type):
1333 '''Set cursor.''' 1334 if action_type == self.POSITION_INSIDE: 1335 set_cursor(self, gtk.gdk.FLEUR) 1336 elif action_type == self.POSITION_TOP_LEFT_CORNER: 1337 set_cursor(self, gtk.gdk.TOP_LEFT_CORNER) 1338 elif action_type == self.POSITION_TOP_RIGHT_CORNER: 1339 set_cursor(self, gtk.gdk.TOP_RIGHT_CORNER) 1340 elif action_type == self.POSITION_BOTTOM_LEFT_CORNER: 1341 set_cursor(self, gtk.gdk.BOTTOM_LEFT_CORNER) 1342 elif action_type == self.POSITION_BOTTOM_RIGHT_CORNER: 1343 set_cursor(self, gtk.gdk.BOTTOM_RIGHT_CORNER) 1344 elif action_type == self.POSITION_TOP_SIDE: 1345 set_cursor(self, gtk.gdk.TOP_SIDE) 1346 elif action_type == self.POSITION_BOTTOM_SIDE: 1347 set_cursor(self, gtk.gdk.BOTTOM_SIDE) 1348 elif action_type == self.POSITION_LEFT_SIDE: 1349 set_cursor(self, gtk.gdk.LEFT_SIDE) 1350 elif action_type == self.POSITION_RIGHT_SIDE: 1351 set_cursor(self, gtk.gdk.RIGHT_SIDE) 1352 else: 1353 set_cursor(self, None)
1354
1355 - def skin_edit_area_get_action_type(self, event):
1356 '''Get action type.''' 1357 ex, ey = event.x, event.y 1358 resize_x = self.padding_x + self.shadow_padding + self.resize_x 1359 resize_y = self.padding_y + self.shadow_padding + self.resize_y 1360 edit_area_rect = self.get_allocation() 1361 1362 if not is_in_rect((ex, ey), (0, 0, edit_area_rect.width, edit_area_rect.height)): 1363 return self.POSITION_OUTSIDE 1364 elif is_in_rect((ex, ey), 1365 (resize_x - self.resize_pointer_size / 2, 1366 resize_y - self.resize_pointer_size / 2, 1367 self.resize_pointer_size, 1368 self.resize_pointer_size)): 1369 return self.POSITION_TOP_LEFT_CORNER 1370 elif is_in_rect((ex, ey), 1371 (resize_x + self.resize_pointer_size / 2, 1372 resize_y - self.resize_pointer_size / 2, 1373 self.resize_width - self.resize_pointer_size, 1374 self.resize_pointer_size)): 1375 return self.POSITION_TOP_SIDE 1376 elif is_in_rect((ex, ey), 1377 (resize_x + self.resize_width - self.resize_pointer_size / 2, 1378 resize_y - self.resize_pointer_size / 2, 1379 self.resize_pointer_size, 1380 self.resize_pointer_size)): 1381 return self.POSITION_TOP_RIGHT_CORNER 1382 elif is_in_rect((ex, ey), 1383 (resize_x - self.resize_pointer_size / 2, 1384 resize_y + self.resize_pointer_size / 2, 1385 self.resize_pointer_size, 1386 self.resize_height - self.resize_pointer_size)): 1387 return self.POSITION_LEFT_SIDE 1388 elif is_in_rect((ex, ey), 1389 (resize_x + self.resize_width - self.resize_pointer_size / 2, 1390 resize_y + self.resize_pointer_size / 2, 1391 self.resize_pointer_size, 1392 self.resize_height - self.resize_pointer_size)): 1393 return self.POSITION_RIGHT_SIDE 1394 elif is_in_rect((ex, ey), 1395 (resize_x - self.resize_pointer_size / 2, 1396 resize_y + self.resize_height - self.resize_pointer_size / 2, 1397 self.resize_pointer_size, 1398 self.resize_pointer_size)): 1399 return self.POSITION_BOTTOM_LEFT_CORNER 1400 elif is_in_rect((ex, ey), 1401 (resize_x + self.resize_pointer_size / 2, 1402 resize_y + self.resize_height - self.resize_pointer_size / 2, 1403 self.resize_width - self.resize_pointer_size, 1404 self.resize_pointer_size)): 1405 return self.POSITION_BOTTOM_SIDE 1406 elif is_in_rect((ex, ey), 1407 (resize_x + self.resize_width - self.resize_pointer_size / 2, 1408 resize_y + self.resize_height - self.resize_pointer_size / 2, 1409 self.resize_pointer_size, 1410 self.resize_pointer_size)): 1411 return self.POSITION_BOTTOM_RIGHT_CORNER 1412 elif is_in_rect((ex, ey), 1413 (resize_x + self.resize_pointer_size / 2, 1414 resize_y + self.resize_pointer_size / 2, 1415 self.resize_width - self.resize_pointer_size, 1416 self.resize_height - self.resize_pointer_size)): 1417 return self.POSITION_INSIDE 1418 else: 1419 return self.POSITION_OUTSIDE
1420
1421 - def is_in_resize_area(self, event):
1422 '''Is at resize area.''' 1423 offset_x = self.padding_x + self.shadow_padding 1424 offset_y = self.padding_y + self.shadow_padding 1425 return is_in_rect( 1426 (event.x, event.y), 1427 (self.resize_x + offset_x - self.resize_pointer_size / 2, 1428 self.resize_y + offset_y - self.resize_pointer_size / 2, 1429 self.resize_width + self.resize_pointer_size, 1430 self.resize_height + self.resize_pointer_size))
1431
1432 - def skin_edit_area_resize(self, action_type, event):
1433 '''Resize.''' 1434 if action_type == self.POSITION_LEFT_SIDE: 1435 self.skin_edit_area_adjust_left(event) 1436 self.queue_draw() 1437 elif action_type == self.POSITION_TOP_SIDE: 1438 self.skin_edit_area_adjust_top(event) 1439 self.queue_draw() 1440 elif action_type == self.POSITION_RIGHT_SIDE: 1441 self.skin_edit_area_adjust_right(event) 1442 self.queue_draw() 1443 elif action_type == self.POSITION_BOTTOM_SIDE: 1444 self.skin_edit_area_adjust_bottom(event) 1445 self.queue_draw() 1446 elif action_type == self.POSITION_TOP_LEFT_CORNER: 1447 self.skin_edit_area_adjust_top(event) 1448 self.skin_edit_area_adjust_left(event) 1449 self.queue_draw() 1450 elif action_type == self.POSITION_TOP_RIGHT_CORNER: 1451 self.skin_edit_area_adjust_top(event) 1452 self.skin_edit_area_adjust_right(event) 1453 self.queue_draw() 1454 elif action_type == self.POSITION_BOTTOM_LEFT_CORNER: 1455 self.skin_edit_area_adjust_bottom(event) 1456 self.skin_edit_area_adjust_left(event) 1457 self.queue_draw() 1458 elif action_type == self.POSITION_BOTTOM_RIGHT_CORNER: 1459 self.skin_edit_area_adjust_bottom(event) 1460 self.skin_edit_area_adjust_right(event) 1461 self.queue_draw()
1462
1463 - def skin_edit_area_adjust_left(self, event):
1464 '''Adjust left.''' 1465 offset_x = self.padding_x + self.shadow_padding 1466 if self.lock_flag: 1467 new_resize_x = min(int(event.x) - offset_x, 0) 1468 new_resize_width = int(self.resize_width + self.resize_x - new_resize_x) 1469 new_resize_height = int(new_resize_width * self.background_pixbuf.get_height() / self.background_pixbuf.get_width()) 1470 1471 if self.resize_height + self.resize_y - new_resize_height > 0: 1472 self.resize_height += int(self.resize_y) 1473 self.resize_y = 0 1474 new_resize_width = int(self.resize_height * self.background_pixbuf.get_width() / self.background_pixbuf.get_height()) 1475 self.resize_x = int(self.resize_width + self.resize_x - new_resize_width) 1476 self.resize_width = int(new_resize_width) 1477 else: 1478 self.resize_width = int(new_resize_width) 1479 self.resize_x = int(new_resize_x) 1480 self.resize_y = int(self.resize_height + self.resize_y - new_resize_height) 1481 self.resize_height = int(new_resize_height) 1482 else: 1483 new_resize_x = min(int(event.x) - offset_x, 0) 1484 self.resize_width = int(self.resize_width + self.resize_x - new_resize_x) 1485 self.resize_x = int(new_resize_x)
1486
1487 - def skin_edit_area_adjust_top(self, event):
1488 '''Adjust top.''' 1489 offset_y = self.padding_y + self.shadow_padding 1490 if self.lock_flag: 1491 new_resize_y = min(int(event.y) - offset_y, 0) 1492 new_resize_height = int(self.resize_height + self.resize_y - new_resize_y) 1493 new_resize_width = int(new_resize_height * self.background_pixbuf.get_width() / self.background_pixbuf.get_height()) 1494 1495 if self.resize_width + self.resize_x - new_resize_width > 0: 1496 self.resize_width += int(self.resize_x) 1497 self.resize_x = 0 1498 new_resize_height = int(self.resize_width * self.background_pixbuf.get_height() / self.background_pixbuf.get_width()) 1499 self.resize_y = int(self.resize_height + self.resize_y - new_resize_height) 1500 self.resize_height = int(new_resize_height) 1501 else: 1502 self.resize_height = int(new_resize_height) 1503 self.resize_y = int(new_resize_y) 1504 self.resize_x = int(self.resize_width + self.resize_x - new_resize_width) 1505 self.resize_width = int(new_resize_width) 1506 else: 1507 new_resize_y = min(int(event.y) - offset_y, 0) 1508 self.resize_height = int(self.resize_height + self.resize_y - new_resize_y) 1509 self.resize_y = int(new_resize_y)
1510
1511 - def skin_edit_area_adjust_right(self, event):
1512 '''Adjust right.''' 1513 offset_x = self.padding_x + self.shadow_padding 1514 if self.lock_flag: 1515 new_resize_width = max(int(event.x) - self.resize_x - offset_x, self.min_resize_width - self.resize_x) 1516 new_resize_height = int(new_resize_width * self.background_pixbuf.get_height() / self.background_pixbuf.get_width()) 1517 1518 if new_resize_height + self.resize_y < self.min_resize_height: 1519 self.resize_height = int(self.min_resize_height - self.resize_y) 1520 self.resize_width = int(self.resize_height * self.background_pixbuf.get_width() / self.background_pixbuf.get_height()) 1521 else: 1522 self.resize_width = int(new_resize_width) 1523 self.resize_height = int(new_resize_height) 1524 else: 1525 new_resize_x = max(offset_x + self.min_resize_width, int(event.x)) 1526 self.resize_width = int(new_resize_x - self.resize_x - offset_x)
1527
1528 - def skin_edit_area_adjust_bottom(self, event):
1529 '''Adjust bottom.''' 1530 offset_y = self.padding_y + self.shadow_padding 1531 if self.lock_flag: 1532 new_resize_height = max(int(event.y) - self.resize_y - offset_y, self.min_resize_height - self.resize_y) 1533 new_resize_width = int(new_resize_height * self.background_pixbuf.get_width() / self.background_pixbuf.get_height()) 1534 1535 if new_resize_width + self.resize_x < self.min_resize_width: 1536 self.resize_width = int(self.min_resize_width - self.resize_x) 1537 self.resize_height = int(self.resize_width * self.background_pixbuf.get_height() / self.background_pixbuf.get_width()) 1538 else: 1539 self.resize_height = int(new_resize_height) 1540 self.resize_width = int(new_resize_width) 1541 else: 1542 new_resize_y = max(offset_y + self.min_resize_height, int(event.y)) 1543 self.resize_height = int(new_resize_y - self.resize_y - offset_y)
1544
1545 - def skin_edit_area_drag_background(self, event):
1546 '''Drag background.''' 1547 new_resize_x = int(event.x) - self.drag_start_x + self.drag_background_x 1548 new_resize_y = int(event.y) - self.drag_start_y + self.drag_background_y 1549 self.resize_x = min(max(new_resize_x, self.min_resize_width - self.resize_width), 0) 1550 self.resize_y = min(max(new_resize_y, self.min_resize_height - self.resize_height), 0) 1551 1552 self.queue_draw()
1553
1554 - def update_skin_config(self):
1555 '''Update skin config.''' 1556 self.resize_scale_x = skin_config.scale_x 1557 self.resize_scale_y = skin_config.scale_y 1558 self.resize_x = self.eval_scale(skin_config.x * self.resize_scale_x) 1559 self.resize_y = self.eval_scale(skin_config.y * self.resize_scale_y) 1560 self.resize_width = int(self.eval_scale(self.background_pixbuf.get_width() * self.resize_scale_x)) 1561 self.resize_height = int(self.eval_scale(self.background_pixbuf.get_height() * self.resize_scale_y))
1562
1563 - def click_reset_button(self):
1564 '''Click reset button.''' 1565 # Reset skin config. 1566 skin_config.reset() 1567 1568 # Update skin config. 1569 self.update_skin_config() 1570 1571 # Apply and save skin. 1572 skin_config.apply_skin() 1573 skin_config.save_skin()
1574
1575 - def click_auto_resize_button(self):
1576 '''Click auto resize button.''' 1577 # Auto resize skin config. 1578 skin_config.auto_resize() 1579 1580 # Update skin config. 1581 self.update_skin_config() 1582 1583 # Apply and save skin. 1584 skin_config.apply_skin() 1585 skin_config.save_skin()
1586
1587 - def update_lock_status(self, toggle_button):
1588 '''Update lock status.''' 1589 self.lock_flag = toggle_button.get_active()
1590 1591 gobject.type_register(SkinEditArea) 1592 1593 if __name__ == '__main__': 1594 skin_window = SkinWindow() 1595 1596 skin_window.show_all() 1597 1598 gtk.main() 1599