1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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"]
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)
75
76 self.skin_dirs = skin_dirs
77 self.add_skin_icon = add_skin_icon
78 self.add_add_icon = add_add_icon
79
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()
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
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
126 '''
127 Internal function to change skin with given item.
128 '''
129
130 if skin_config.reload_skin(os.path.basename(item.skin_dir)):
131 skin_config.apply_skin()
132
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
148 '''
149 Internal function to switch edit page.
150 '''
151
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
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
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
249 create_directory(skin_dir, True)
250
251
252 shutil.copy(filepath, skin_dir)
253
254
255 touch_file(config_file)
256
257
258 Config(config_file, default_config).write()
259
260
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
274 scroll_to_bottom(self.preview_scrolled_window)
275
276 - def create_skin_from_package(self, filepath):
277 '''Create skin from package.'''
278
279 skin_dir = os.path.join(skin_config.user_skin_dir, str(uuid.uuid4()))
280
281
282 create_directory(skin_dir, True)
283
284
285 tar = tarfile.open(filepath, "r:gz")
286 tar.extractall(skin_dir)
287
288
289 config = Config(os.path.join(skin_dir, "config.ini"))
290 config.load()
291
292
293 skin_theme_name = config.get("theme", "theme_name")
294 if not skin_theme_name in COLOR_SEQUENCE:
295
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
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
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
308 remove_directory(os.path.join(skin_dir, "ui_theme"))
309 remove_directory(os.path.join(skin_dir, "app_theme"))
310 else:
311
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
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
333 scroll_to_bottom(self.preview_scrolled_window)
334
335 - def highlight_skin(self):
336 '''Highlight skin.'''
337
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
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
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
364 remove_directory(item.skin_dir)
365
366
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)
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
413
414
415 self.config = Config(os.path.join(self.skin_dir, "config.ini"))
416 self.config.load()
417
427
437
439 '''Is deletable.'''
440 return self.config.getboolean("action", "deletable")
441
443 '''Is editable.'''
444 return self.config.getboolean("action", "editable")
445
447 '''Emit redraw-request signal.'''
448 self.emit("redraw-request")
449
451 '''Get width.'''
452 return self.width + (self.icon_padding + self.padding_x) * 2
453
455 '''Get height.'''
456 return self.height + (self.icon_padding + self.padding_y) * 2
457
459 '''Render item.'''
460
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
474 with cairo_state(cr):
475
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
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
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
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
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
559
564
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
581
583 '''Set item with normal status.'''
584 self.highlight_flag = False
585
586 self.emit_redraw_request()
587
610
626
628 '''Handle single click event.'''
629 pass
630
632 '''Handle double click event.'''
633 pass
634
635 gobject.type_register(SkinPreviewIcon)
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
658 '''Emit redraw-request signal.'''
659 self.emit("redraw-request")
660
662 '''Get width.'''
663 return self.width + (self.icon_padding + self.padding_x) * 2
664
666 '''Get height.'''
667 return self.height + (self.icon_padding + self.padding_y) * 2
668
694
696 '''Handle `motion-notify-event` signal.'''
697 self.hover_flag = True
698
699 self.emit_redraw_request()
700
706
712
714 '''Set item with normal status.'''
715 self.highlight_flag = False
716
717 self.emit_redraw_request()
718
722
726
728 '''Handle single click event.'''
729 pass
730
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
773 if skin_config.scale_x == 1.0 and skin_config.scale_y == 1.0:
774 action_index = 1
775
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
875 self.highlight_color_icon(item.color)
876
877
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)
896 '''Icon item.'''
897
898 __gsignals__ = {
899 "redraw-request" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
900 }
901
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
914 '''Emit redraw-request signal.'''
915 self.emit("redraw-request")
916
918 '''Get width.'''
919 return self.width + self.padding_x * 2
920
922 '''Get height.'''
923 return self.height + self.padding_y * 2
924
951
953 '''Handle `motion-notify-event` signal.'''
954 self.hover_flag = True
955
956 self.emit_redraw_request()
957
963
969
971 '''Set item with normal status.'''
972 self.highlight_flag = False
973
974 self.emit_redraw_request()
975
979
983
985 '''Handle single click event.'''
986 pass
987
989 '''Handle double click event.'''
990 pass
991
992 gobject.type_register(ColorIconItem)
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
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)
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
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
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
1064 '''Eval scale.'''
1065 return value * self.preview_pixbuf_width / self.app_window_width
1066
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
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
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
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
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
1153 cr.set_source_rgb(0, 1, 1)
1154
1155
1156 cr.rectangle(
1157 resize_x,
1158 resize_y - self.resize_frame_size / 2,
1159 self.resize_width,
1160 self.resize_frame_size)
1161 cr.rectangle(
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(
1167 resize_x - self.resize_frame_size / 2,
1168 resize_y,
1169 self.resize_frame_size,
1170 self.resize_height)
1171 cr.rectangle(
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
1178 cr.arc(
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(
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(
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(
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(
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(
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(
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(
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
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
1260
1291
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
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
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
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
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
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
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
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
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
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
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
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
1574
1586
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