RoundTransparentWindow
======================

* :download:`Download example <PyObjCExample-RoundTransparentWindow.zip>`

Port of the RoundTransparentWindow example at ADC.


.. rst-class:: tabber

Sources
-------

.. rst-class:: tabbertab

RoundTransparentWindow.py
.........................

.. sourcecode:: python

    import sys
    from math import floor
    
    import Cocoa
    import objc
    from objc import super  # noqa: A004
    from PyObjCTools import AppHelper
    
    
    class Controller(Cocoa.NSObject):
        itsWindow = objc.IBOutlet()
    
        @objc.IBAction
        def changeTransparency_(self, sender):
            """."""
            self.itsWindow.setAlphaValue_(sender.floatValue())
            self.itsWindow.display()
    
    
    class CustomView(Cocoa.NSView):
        circleImage = objc.ivar()
        pentaImage = objc.ivar()
    
        def awakeFromNib(self):
            self.circleImage = Cocoa.NSImage.imageNamed_("circle")
            if self.circleImage is None:
                sys.stderr.write("failed to access circle image\n")
                raise RuntimeError
            self.pentaImage = Cocoa.NSImage.imageNamed_("pentagram")
            if self.pentaImage is None:
                sys.stderr.write("failed to access pentagram image\n")
                raise RuntimeError
            self.setNeedsDisplay_(True)
    
        def drawRect_(self, rect):
            Cocoa.NSColor.clearColor().set()
            Cocoa.NSRectFill(self.frame())
            if self.window().alphaValue() > 0.7:
                self.circleImage.compositeToPoint_operation_(
                    Cocoa.NSZeroPoint, Cocoa.NSCompositeSourceOver
                )
            else:
                self.pentaImage.compositeToPoint_operation_(
                    Cocoa.NSZeroPoint, Cocoa.NSCompositeSourceOver
                )
    
            if floor(Cocoa.NSAppKitVersionNumber) <= Cocoa.NSAppKitVersionNumber10_1:
                self.window().setHasShadow_(False)
                self.window().setHasShadow_(True)
            else:
                self.window().invalidateShadow()
    
    
    class CustomWindow(Cocoa.NSWindow):
        def awakeFromNib(self):
            self.initialLocation = Cocoa.NSPoint()
    
        def initWithContentRect_styleMask_backing_defer_(
            self, contentRect, aStyle, bufferingType, flag
        ):
            result = super().initWithContentRect_styleMask_backing_defer_(
                contentRect,
                Cocoa.NSBorderlessWindowMask,
                Cocoa.NSBackingStoreBuffered,
                False,
            )
            if result is None:
                sys.stderr.write("superclass call failed\n")
                raise RuntimeError
            result.setBackgroundColor_(Cocoa.NSColor.clearColor())
            result.setLevel_(Cocoa.NSStatusWindowLevel)
            result.setAlphaValue_(1.0)
            result.setOpaque_(False)
            result.setHasShadow_(True)
            return result
    
        def canBecomeKeyWindow(self):
            return True
    
        def mouseDragged_(self, theEvent):
            screenFrame = Cocoa.NSScreen.mainScreen().frame()
            if screenFrame is None:
                sys.stderr.write("failed to obtain screen\n")
                raise RuntimeError
            windowFrame = self.frame()
            if windowFrame is None:
                sys.stderr.write("failed to obtain frame\n")
                raise RuntimeError
            currentLocation = self.convertBaseToScreen_(
                self.mouseLocationOutsideOfEventStream()
            )
            newOrigin = Cocoa.NSMakePoint(
                (currentLocation.x - self.initialLocation.x),
                (currentLocation.y - self.initialLocation.y),
            )
            if (newOrigin.y + windowFrame.size.height) > (
                screenFrame.origin.y + screenFrame.size.height
            ):
                newOrigin.y = screenFrame.origin.y + (
                    screenFrame.size.height + windowFrame.size.height
                )
            self.setFrameOrigin_(newOrigin)
    
        def mouseDown_(self, theEvent):
            windowFrame = self.frame()
            if windowFrame is None:
                sys.stderr.write("failed to obtain frame\n")
                raise RuntimeError
            self.initialLocation = self.convertBaseToScreen_(theEvent.locationInWindow())
            self.initialLocation.x -= windowFrame.origin.x
            self.initialLocation.y -= windowFrame.origin.y
    
    
    if __name__ == "__main__":
        AppHelper.runEventLoop()

.. rst-class:: tabbertab

setup.py
........

.. sourcecode:: python

    """
    Script for building the example.
    
    Usage:
        python3 setup.py py2app
    """
    
    from setuptools import setup
    
    setup(
        app=["RoundTransparentWindow.py"],
        data_files=["MainMenu.nib", "circle.tif", "pentagram.tif"],
        setup_requires=["py2app", "pyobjc-framework-Cocoa"],
    )

