1"""DotView.py -- A one-window app demonstrating how to write a custom NSView. 2 3To build the demo program, run this line in Terminal.app: 4 5 $ python setup.py py2app -A 6 7This creates a directory "dist" containing DotView.app. (The 8-A option causes the files to be symlinked to the .app bundle instead 9of copied. This means you don't have to rebuild the app if you edit the 10sources or nibs.) 11""" 12 13# Created by Etienne Posthumus on Thu Dec 26 2002, after Apple's 14# ObjC DotView example. 15# Edited and enhanced by JvR, 2003. 16# 17# The main difference with the Apple DotView demo is that our custom view 18# is embedded in a scroll view. It turns out that this is almost no work 19# in InterfaceBuilder (select the view, then go to Layout -> Make subvies of 20# -> Scroll View), and *no* work in the code. It was too easy, so for kicks 21# I added zoom functionality and a "Show rulers" checkbox. 22 23from Cocoa import * 24from PyObjCTools import AppHelper 25 26ZOOM = 2.0 27 28 29# class defined in MainMenu.nib 30class DotView(NSView): 31 colorWell = objc.IBOutlet() 32 sizeSlider = objc.IBOutlet() 33 34 def initWithFrame_(self, frame): 35 self.center = (50.0, 50.0) 36 super(DotView, self).initWithFrame_(frame) 37 self.radius = 10.0 38 self.color = NSColor.redColor() 39 return self 40 41 def awakeFromNib(self): 42 self.colorWell.setColor_(self.color) 43 self.sizeSlider.setFloatValue_(self.radius) 44 scrollView = self.superview().superview() 45 scrollView.setHasHorizontalRuler_(1) 46 scrollView.setHasVerticalRuler_(1) 47 48 @objc.IBAction 49 def zoomIn_(self, sender): 50 (x, y), (bw, bh) = self.bounds() 51 (x, y), (fw, fh) = self.frame() 52 self.setBoundsSize_((bw / ZOOM, bh / ZOOM)) 53 self.setFrameSize_((fw * ZOOM, fh * ZOOM)) 54 self.setNeedsDisplay_(True) 55 56 @objc.IBAction 57 def zoomOut_(self, sender): 58 (x, y), (bw, bh) = self.bounds() 59 (x, y), (fw, fh) = self.frame() 60 self.setBoundsSize_((bw * ZOOM, bh * ZOOM)) 61 self.setFrameSize_((fw / ZOOM, fh / ZOOM)) 62 self.setNeedsDisplay_(True) 63 64 @objc.IBAction 65 def setRulersVisible_(self, button): 66 scrollView = self.superview().superview() 67 scrollView.setRulersVisible_(button.state()) 68 69 def isOpaque(self): 70 return True 71 72 def mouseDown_(self, event): 73 eventLocation = event.locationInWindow() 74 if event.modifierFlags() & NSCommandKeyMask: 75 clipView = self.superview() 76 self.originalPoint = eventLocation 77 self.originalOffset = clipView.bounds()[0] 78 else: 79 self.center = self.convertPoint_fromView_(eventLocation, None) 80 self.setNeedsDisplay_(True) 81 self.autoscroll_(event) 82 83 def mouseDragged_(self, event): 84 if event.modifierFlags() & NSCommandKeyMask: 85 clipView = self.superview() 86 eventLocation = event.locationInWindow() 87 ox, oy = self.originalPoint 88 x, y = eventLocation 89 dx, dy = x - ox, y - oy 90 x, y = self.originalOffset 91 ox, oy = clipView.constrainScrollPoint_((x - dx, y - dy)) 92 clipView.scrollToPoint_((ox, oy)) 93 clipView.superview().reflectScrolledClipView_(clipView) 94 else: 95 self.mouseDown_(event) 96 97 def drawRect_(self, rect): 98 NSColor.whiteColor().set() 99 NSRectFill(self.bounds()) 100 origin = (self.center[0]-self.radius, self.center[1]-self.radius) 101 size = (2 * self.radius, 2 * self.radius) 102 dotRect = (origin, size) 103 self.color.set() 104 NSBezierPath.bezierPathWithOvalInRect_(dotRect).fill() 105 106 @objc.IBAction 107 def setRadius_(self, sender): 108 self.radius = sender.floatValue() 109 self.setNeedsDisplay_(True) 110 111 @objc.IBAction 112 def setColor_(self, sender): 113 self.color = sender.color() 114 self.setNeedsDisplay_(True) 115 116 117if __name__ == "__main__": 118 AppHelper.runEventLoop() 119