home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / gui / pref / iconeditor.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  19.9 KB  |  552 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from __future__ import division
  6. if __name__ == '__main__':
  7.     
  8.     __builtins__._ = lambda s: s
  9.  
  10. from traceback import print_exc
  11. from util import debug_property
  12. import config
  13. IMAGE_WILDCARD = 'Image files (*.bmp;*.gif;*.jpeg;*.jpg;*.png)|*.bmp;*.gif;*.jpeg;*.jpg;*.png|All files (*.*)|*.*'
  14. from wx import BufferedPaintDC, ImageFromString, Size, Point, GetMousePosition, Bitmap, ImageFromBitmap, BitmapFromImage
  15. from gui.windowfx import ApplySmokeAndMirrors
  16. import wx
  17. from PIL import Image
  18. from cStringIO import StringIO
  19. from util.primitives.error_handling import traceguard
  20. from util.primitives.funcs import do
  21. from path import path
  22. from logging import getLogger
  23. log = getLogger('iconeditor')
  24. info = log.info
  25. MAX_BICON_SIZE = (128, 128)
  26.  
  27. class IconEditor(wx.Dialog):
  28.     def_size = (295, 415)
  29.     
  30.     def __init__(self, parent, icon = None):
  31.         wx.Dialog.__init__(self, parent, -1, _('Set Buddy Icon'), size = self.def_size)
  32.         self.Sizer = s = wx.BoxSizer(wx.VERTICAL)
  33.         self.ReturnCode = wx.ID_CANCEL
  34.         self.iconedit = IconEditPanel(self, icon)
  35.         s.Add(self.iconedit, 1, wx.EXPAND)
  36.         self.Fit()
  37.  
  38.     
  39.     def Bytes(self):
  40.         return self.iconedit.Bytes
  41.  
  42.     Bytes = property(Bytes)
  43.     
  44.     def ImageChanged(self):
  45.         return self.iconedit.dragger._image_changed
  46.  
  47.     ImageChanged = property(ImageChanged)
  48.     
  49.     def Prompt(self, okCallback):
  50.         self.okCallback = okCallback
  51.         self.Show(True)
  52.         
  53.         def onclose(e):
  54.             self.Show(False)
  55.             if self.ReturnCode in (wx.ID_SAVE, wx.ID_OK):
  56.                 self.okCallback()
  57.             
  58.             e.Skip(True)
  59.             wx.CallAfter(self.Destroy)
  60.  
  61.         self.Bind(wx.EVT_CLOSE, onclose)
  62.  
  63.  
  64.  
  65. class IconDragger(wx.Panel):
  66.     normal = 48
  67.     maxpick = 128
  68.     
  69.     def __init__(self, parent, slider):
  70.         wx.Panel.__init__(self, parent, style = wx.SUNKEN_BORDER)
  71.         Bind = self.Bind
  72.         Bind(wx.EVT_PAINT, self.on_paint)
  73.         Bind(wx.EVT_ERASE_BACKGROUND, (lambda e: pass))
  74.         Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
  75.         Bind(wx.EVT_RIGHT_DOWN, self.on_right_down)
  76.         Bind(wx.EVT_LEFT_UP, self.on_mouse_up)
  77.         Bind(wx.EVT_MOTION, self.on_motion)
  78.         Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.on_mouse_capture_lost)
  79.         Bind(wx.EVT_KEY_DOWN, self.on_key)
  80.         self.bitmap = wx.TransparentBitmap(32, 32)
  81.         self.adjustment = (0, 0)
  82.         self.dragging = False
  83.         self.picksize = wx.Size(self.normal, self.normal)
  84.         self.slider = slider
  85.         slider.Bind((wx.EVT_SLIDER,), (lambda e: self.on_slider(e, high_quality = False)))
  86.         slider.Bind((wx.EVT_SCROLL_CHANGED,), (lambda e: wx.CallAfter((lambda e = (e,): self.on_slider(e, high_quality = True)))
  87. ))
  88.         self._image_changed = False
  89.         self._image_bytes = None
  90.         sz = (260, 260)
  91.         self.SetMinSize(sz)
  92.         self.SetMaxSize(sz)
  93.         self.SetSize(sz)
  94.         SimpleDropTarget = SimpleDropTarget
  95.         import gui.toolbox.dnd
  96.         self.SetDropTarget(SimpleDropTarget(self))
  97.         self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
  98.  
  99.     
  100.     def OnDropFiles(self, filelist):
  101.         for filepath in (lambda .0: for f in .0:
  102. path(f))(filelist):
  103.             if filepath.isfile():
  104.                 traceguard.__enter__()
  105.                 
  106.                 try:
  107.                     img = Image.open(filepath)
  108.                     img.load()
  109.                     return self.set_image(img.WX)
  110.                 finally:
  111.                     pass
  112.  
  113.                 continue
  114.             traceguard.__exit__
  115.         
  116.         log.warning('no images in %r', filelist)
  117.  
  118.     
  119.     def OnDropBitmap(self, bitmap):
  120.         self.set_image(bitmap)
  121.  
  122.     
  123.     def on_slider(self, e = None, high_quality = True):
  124.         n = self.resize_func(self.slider.Value, high_quality = high_quality)
  125.         self.picksize = Size(n, n)
  126.         self.Refresh()
  127.         if e is not None:
  128.             self._image_changed = True
  129.             self._image_bytes = None
  130.         
  131.  
  132.     
  133.     def _resized_high(self, width, height):
  134.         return self.image.PIL.Resized((width, height))
  135.  
  136.     
  137.     def _resized_low(self, width, height):
  138.         return self.image.Scale(width, height)
  139.  
  140.     
  141.     def resize_image(self, dim, high_quality = True):
  142.         w = self.image.Width
  143.         h = self.image.Height
  144.         s = None if high_quality else self._resized_low
  145.         new_image = None if w < h else s(dim, (h / w) * dim)
  146.         self.bitmap = new_image.WXB
  147.  
  148.     
  149.     def on_paint(self, e = None):
  150.         dc = BufferedPaintDC(self)
  151.         b = wx.WHITE_BRUSH
  152.         dc.Brush = b
  153.         dc.Pen = wx.TRANSPARENT_PEN
  154.         dc.DrawRectangle(0, 0, *self.Size)
  155.         self.paint_bitmap(dc)
  156.         dc.Brush = wx.TRANSPARENT_BRUSH
  157.         dc.Pen = wx.RED_PEN
  158.         (x, y) = self.middle
  159.         x -= self.picksize[0] / 2
  160.         y -= self.picksize[1] / 2
  161.         dc.SetLogicalFunction(wx.INVERT)
  162.         dc.DrawRectangle(x, y, self.picksize[0], self.picksize[1])
  163.  
  164.     
  165.     def paint_bitmap(self, dc, pickerPos = None):
  166.         bw = self.bitmap.Width
  167.         bh = self.bitmap.Height
  168.         imagecenter = Point(self.Rect.Width / 2, self.Rect.Height / 2) - Point(bw / 2, bh / 2)
  169.         xy = imagecenter + (self.adjustment[0] * bw, self.adjustment[1] * bh)
  170.         if dc is not None:
  171.             dc.DrawBitmap(self.bitmap, *xy)
  172.         else:
  173.             pickWidth = int(self.picksize[0])
  174.             pickHeight = int(self.picksize[1])
  175.             if not pickerPos:
  176.                 pass
  177.             pickRect = wx.RectPS((self.Rect.width // 2 - self.picksize[0] // 2, self.Rect.height // 2 - self.picksize[1] // 2), (pickWidth, pickHeight))
  178.             pickRect.Position -= xy
  179.             imageRect = wx.RectPS((0, 0), (bw, bh))
  180.             cropRect = imageRect.Intersect(pickRect)
  181.             crop_box = (cropRect.left, cropRect.top, cropRect.right, cropRect.bottom)
  182.             croppedImage = self.bitmap.PIL.crop(crop_box)
  183.             offsetX = max(-(pickRect.x - cropRect.x), 0)
  184.             offsetY = max(-(pickRect.y - cropRect.y), 0)
  185.             if offsetX or offsetY:
  186.                 paddedImage = Image.new('RGBA', (pickRect.width, pickRect.height), (0, 0, 0, 0))
  187.                 paddedImage.paste(croppedImage, (offsetX, offsetY))
  188.                 return paddedImage
  189.             return croppedImage
  190.         return dc is not None
  191.  
  192.     
  193.     def middle(self):
  194.         (w, h) = self.Size
  195.         return Point(w / 2, h / 2)
  196.  
  197.     middle = property(middle)
  198.     
  199.     def Bytes(self):
  200.         s = self.picksize
  201.         r = self.Rect
  202.         pickerPos = (r.Width // 2 - s[0] // 2, r.Height // 2 - s[1] // 2)
  203.         img = self.paint_bitmap(None, pickerPos)
  204.         imgFile = StringIO()
  205.         img.save(imgFile, 'PNG', optimize = True)
  206.         return imgFile.getvalue()
  207.  
  208.     Bytes = debug_property(Bytes)
  209.     
  210.     def on_mouse_capture_lost(self, event):
  211.         self.CancelDrag()
  212.  
  213.     
  214.     def on_mouse_down(self, e):
  215.         e.Skip()
  216.         if e.LeftDown():
  217.             self.startdrag = self.dragging = GetMousePosition()
  218.             self.CaptureMouse()
  219.         
  220.  
  221.     
  222.     def on_right_down(self, event):
  223.         if self.dragging:
  224.             self.CancelDrag()
  225.         else:
  226.             event.Skip()
  227.  
  228.     
  229.     def on_key(self, event):
  230.         isesc = event.KeyCode == wx.WXK_ESCAPE
  231.         if self.dragging and isesc:
  232.             self.CancelDrag()
  233.         elif not isesc:
  234.             event.Skip()
  235.         
  236.  
  237.     
  238.     def CancelDrag(self):
  239.         startdrag = self.startdrag
  240.         curdrag = self.dragging
  241.         self.on_mouse_up()
  242.         self.dragging = curdrag
  243.         self.on_motion(forcednewpos = startdrag)
  244.         self.dragging = False
  245.  
  246.     
  247.     def on_motion(self, e = None, forcednewpos = None):
  248.         if self.dragging is not False:
  249.             if not forcednewpos:
  250.                 pass
  251.             newpos = GetMousePosition()
  252.             delta = newpos - Point(*self.dragging)
  253.             diff = (float(delta.x) / self.bitmap.Width, float(delta.y) / self.bitmap.Height)
  254.             self.adjustment = (self.adjustment[0] + diff[0], self.adjustment[1] + diff[1])
  255.             self.dragging = newpos
  256.             self.Refresh()
  257.             self._image_changed = True
  258.             self._image_bytes = None
  259.         
  260.  
  261.     
  262.     def on_mouse_up(self, e = None):
  263.         if not e or e.LeftUp():
  264.             self.startdrag = None
  265.             self.dragging = False
  266.             while self.HasCapture():
  267.                 self.ReleaseMouse()
  268.         
  269.  
  270.     
  271.     def set_image(self, image, first = False):
  272.         self.Parent.set_screen_button_mode()
  273.         if isinstance(image, str):
  274.             log.info('set_image received bytes')
  275.             self._image_bytes = image
  276.             image = ImageFromString(image)
  277.         
  278.         if not first:
  279.             self._image_changed = True
  280.         
  281.         self._set_imageorbitmap(image)
  282.         self.dim = max(self.image.Width, self.image.Height)
  283.         if self.dim > max(MAX_BICON_SIZE):
  284.             self._image_changed = True
  285.         
  286.         self.adjustment = (0, 0)
  287.         if self.image.Width == self.normal and self.image.Height == self.normal:
  288.             self.slider.Enable(False)
  289.             self.picksize = Size(self.normal, self.normal)
  290.         else:
  291.             self.slider.Enable(True)
  292.             if self.dim < self.normal:
  293.                 f = self.f1
  294.             elif self.dim < self.maxpick:
  295.                 f = self.f2
  296.             else:
  297.                 f = self.f3
  298.             self.resize_func = f
  299.             self.on_slider()
  300.         self.Refresh()
  301.  
  302.     
  303.     def f1(self, val, high_quality = True):
  304.         return self.normal - int((self.normal - self.dim) * (val / 100))
  305.  
  306.     
  307.     def f2(self, val, high_quality = True):
  308.         return self.dim - (val / 100) * (self.dim - self.normal)
  309.  
  310.     
  311.     def f3(self, val, high_quality = True):
  312.         mid = 50
  313.         pickval = val - mid
  314.         if pickval < 0:
  315.             pickval = 0
  316.         
  317.         if val < mid:
  318.             dim = (self.dim - self.maxpick) * (val / mid) + self.maxpick
  319.             self.resize_image(dim, high_quality = high_quality)
  320.         else:
  321.             self.resize_image(max(self.image.Width, self.image.Height), high_quality = high_quality)
  322.         return self.maxpick - (pickval / mid) * (self.maxpick - self.normal)
  323.  
  324.     
  325.     def _set_imageorbitmap(self, image):
  326.         if isinstance(image, Bitmap):
  327.             self.image = ImageFromBitmap(image)
  328.             if not self.image.HasAlpha():
  329.                 self.image.InitAlpha()
  330.             
  331.             self.bitmap = image
  332.         elif isinstance(image, wx.Image):
  333.             self.image = image
  334.             if not image.HasAlpha():
  335.                 image.InitAlpha()
  336.             
  337.             self.bitmap = BitmapFromImage(self.image)
  338.         else:
  339.             raise TypeError
  340.         return isinstance(image, Bitmap)
  341.  
  342.  
  343.  
  344. class IconEditPanel(wx.Panel):
  345.     
  346.     def __init__(self, parent, bitmap = None, dialog_buttons = True):
  347.         wx.Panel.__init__(self, parent)
  348.         wx.InitAllImageHandlers()
  349.         self.construct_and_layout(dialog_buttons)
  350.         for b in self.buttonnames:
  351.             self.buttonfor(b).Bind(wx.EVT_BUTTON, getattr(self, 'on_' + b))
  352.         
  353.         if bitmap:
  354.             if not hasattr(bitmap, 'IsOk') or bitmap.IsOk():
  355.                 traceguard.__enter__()
  356.                 
  357.                 try:
  358.                     self.set_image(bitmap, first = True)
  359.                 finally:
  360.                     pass
  361.  
  362.             
  363.         
  364.  
  365.     
  366.     def Bytes(self):
  367.         if self.dragger._image_bytes and not (self.dragger._image_changed):
  368.             log.info('returning original image bytes')
  369.             return self.dragger._image_bytes
  370.         log.info('returning new bytes from resized image')
  371.         return self.dragger.Bytes
  372.  
  373.     Bytes = property(Bytes)
  374.     
  375.     def on_file(self, e):
  376.         filediag = wx.FileDialog(wx.GetTopLevelParent(self), _('Choose an icon'), wildcard = IMAGE_WILDCARD)
  377.         if filediag.ShowModal() == wx.ID_OK:
  378.             imgpath = path(filediag.GetPath())
  379.             if imgpath.isfile():
  380.                 
  381.                 try:
  382.                     Image.open(imgpath).load()
  383.                 except:
  384.                     wx.MessageBox(_('"%s"\n\nis not a valid image.') % imgpath, _('Invalid Image'), style = wx.ICON_ERROR, parent = self)
  385.  
  386.                 self.set_image(imgpath.bytes())
  387.             
  388.         
  389.  
  390.     
  391.     def on_webcam(self, e):
  392.         pass
  393.  
  394.     capture_related = [
  395.         'save']
  396.     
  397.     def set_image(self, img, *a, **k):
  398.         return self.dragger.set_image(img, *a, **k)
  399.  
  400.     
  401.     def on_screen(self, e):
  402.         b = self.buttonfor('screen')
  403.         if b.Label == _('Capture'):
  404.             return self.on_capture()
  405.         b = self.buttonfor('screen')
  406.         b.Label = _('Capture')
  407.         b.SetBold()
  408.         self.slider.Enable(False)
  409.         for b in self.capture_related:
  410.             self.buttonfor(b).Enable(False)
  411.         
  412.         cuthole(self.dragger)
  413.  
  414.     
  415.     def on_capture(self):
  416.         self.slider.Enable(True)
  417.         dragger = self.dragger
  418.         self.Freeze()
  419.         
  420.         try:
  421.             if config.platform == 'win':
  422.                 
  423.                 try:
  424.                     getScreenBitmap = getScreenBitmap
  425.                     import cgui
  426.                 except ImportError:
  427.                     print_exc()
  428.                     return None
  429.  
  430.                 bitmap = getScreenBitmap(wx.RectPS(dragger.ScreenRect.Position, dragger.ClientSize))
  431.             else:
  432.                 screendc = wx.ScreenDC()
  433.                 bitmap = screendc.GetAsBitmap()
  434.             if bitmap is not None:
  435.                 self.set_image(wx.ImageFromBitmap(bitmap))
  436.             
  437.             s = self.slider
  438.             s.Value = (s.Max - s.Min) / 2
  439.         finally:
  440.             wx.CallAfter(self.ThawLater)
  441.  
  442.  
  443.     
  444.     def ThawLater(self):
  445.         
  446.         try:
  447.             self.dragger.on_slider()
  448.         finally:
  449.             self.Thaw()
  450.  
  451.  
  452.     
  453.     def set_screen_button_mode(self):
  454.         b = self.buttonfor('screen')
  455.         if b.Label == _('Capture'):
  456.             b.Label = _('Screen')
  457.             f = b.Font
  458.             f.SetWeight(wx.FONTWEIGHT_NORMAL)
  459.             b.Font = f
  460.             (do,)((lambda .0: for b in .0:
  461. self.buttonfor(b).Enable(True))(self.capture_related))
  462.             ApplySmokeAndMirrors(wx.GetTopLevelParent(self))
  463.         
  464.  
  465.     
  466.     def on_clipboard(self, e):
  467.         cb = wx.TheClipboard
  468.         if cb.IsSupported(wx.DataFormat(wx.DF_BITMAP)):
  469.             data = wx.BitmapDataObject()
  470.             cb.GetData(data)
  471.             self.set_image(data.Bitmap)
  472.         else:
  473.             wx.MessageBox('No image data found in clipboard.', 'Icon From Clipboard')
  474.  
  475.     
  476.     def on_save(self, e):
  477.         self.EndWithReturnCode(wx.ID_OK)
  478.  
  479.     
  480.     def EndWithReturnCode(self, code):
  481.         win = wx.GetTopLevelParent(self)
  482.         while self.dragger.HasCapture():
  483.             self.dragger.ReleaseMouse()
  484.         win.ReturnCode = code
  485.         win.Close()
  486.  
  487.     
  488.     def on_clear(self, e):
  489.         self.set_image(wx.TransparentBitmap(100, 100))
  490.  
  491.     
  492.     def on_cancel(self, e):
  493.         self.EndWithReturnCode(wx.ID_CANCEL)
  494.  
  495.     
  496.     def button_names(self, dialog_buttons):
  497.         names = [
  498.             ('file', _('&File')),
  499.             ('clipboard', _('Cli&pboard')),
  500.             ('screen', _('Scree&n'))]
  501.         if dialog_buttons:
  502.             names += [
  503.                 ('save', _('&Save')),
  504.                 ('clear', _('C&lear')),
  505.                 ('cancel', _('&Cancel'))]
  506.         
  507.         return names
  508.  
  509.     
  510.     def construct_and_layout(self, dialog_buttons):
  511.         top = wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Source'), wx.HORIZONTAL)
  512.         middle = wx.StaticBoxSizer(wx.StaticBox(self, -1, 'Preview'), wx.VERTICAL)
  513.         names = self.button_names(dialog_buttons)
  514.         self.buttonnames = [ name for name, guiname in names ]
  515.         self.buttons = [ wx.Button(self, -1, guiname) for name, guiname in names ]
  516.         []([ (b, 1, wx.EXPAND | wx.ALL, 3) for b in self.buttons[:3] ])
  517.         self.slider = wx.Slider(self)
  518.         self.slider.Disable()
  519.         self.dragger = IconDragger(self, self.slider)
  520.         middle.Add(self.dragger, 1, wx.EXPAND | wx.ALL)
  521.         middle.Add(self.slider, 0, wx.EXPAND | wx.ALL)
  522.         sz.AddMany([
  523.             (top, 0, wx.EXPAND | wx.ALL, 3),
  524.             (middle, 1, wx.EXPAND | wx.ALL, 3)])
  525.  
  526.     
  527.     def buttonfor(self, s):
  528.         return self.buttons[self.buttonnames.index(s)]
  529.  
  530.  
  531.  
  532. def cuthole(ctrl):
  533.     top = wx.GetTopLevelParent(ctrl)
  534.     x = ctrl.ScreenRect.X - top.ScreenRect.X
  535.     y = ctrl.ScreenRect.Y - top.ScreenRect.Y
  536.     (w, h) = ctrl.ClientSize
  537.     winsz = top.Size
  538.     region = wx.Region(0, 0, winsz[0], y)
  539.     region.UnionRect((0, 0, x, winsz[1]))
  540.     region.UnionRect((x + w, y, winsz[0] - w - x, h))
  541.     region.UnionRect((0, y + h, winsz[0], winsz[1] - h - y))
  542.     ApplySmokeAndMirrors(top, region)
  543.  
  544. if __name__ == '__main__':
  545.     
  546.     _ = lambda s: s
  547.     from gui.toolbox import setuplogging
  548.     setuplogging()
  549.     app = wx.PySimpleApp()
  550.     IconEditor(None).ShowModal()
  551.  
  552.