• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.9.5/pyobjc-42/2.5/pyobjc/pyobjc-framework-Cocoa/Examples/AppKit/CocoaBindings/GraphicsBindings/
1#
2#  GraphicsView.py
3#  GraphicsBindings
4#
5#  Converted by u.fiedler on feb 2005
6#  with great help from Bob Ippolito - Thank you Bob!
7#
8#  The original version was written in Objective-C by Malcolm Crawford
9#  http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
10
11PropertyObservationContext = 1091
12GraphicsObservationContext = 1092
13SelectionIndexesObservationContext = 1093
14
15
16from Foundation import *
17from AppKit import *
18from objc import ivar
19from Circle import Circle
20from sets import Set
21
22class GraphicsView(NSView):
23    graphicsContainer = ivar(u'graphicsContainer')
24    graphicsKeyPath   = ivar(u'graphicsKeyPath')
25
26    selectionIndexesContainer = ivar(u'selectionIndexesContainer') # GraphicsArrayController
27    selectionIndexesKeyPath   = ivar(u'selectionIndexesKeyPath')
28
29    oldGraphics = ivar(u'oldGraphics')
30
31    def exposedBindings(self):
32        return [u"graphics", u"selectedObjects"]
33
34    def initWithFrame_(self, frameRect):
35        return super(GraphicsView, self).initWithFrame_(frameRect)
36
37    def graphics(self):
38        if not self.graphicsContainer: return None
39        return self.graphicsContainer.valueForKeyPath_(self.graphicsKeyPath)
40
41    def selectionIndexes(self):
42        if not self.selectionIndexesContainer: return None
43        return self.selectionIndexesContainer.valueForKeyPath_(self.selectionIndexesKeyPath)
44
45    def startObservingGraphics_(self, graphics):
46        if not graphics: return
47        # Register to observe each of the new graphics, and
48        # each of their observable properties -- we need old and new
49        # values for drawingBounds to figure out what our dirty rect
50        for newGraphic in graphics:
51            # Register as observer for all the drawing-related properties
52            newGraphic.addObserver_forKeyPath_options_context_(
53                self, u"drawingBounds", (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld),
54                PropertyObservationContext)
55            keys = Circle.keysForNonBoundsProperties()
56            for key in keys:
57                newGraphic.addObserver_forKeyPath_options_context_(
58                    self, key, 0, PropertyObservationContext)
59
60    def stopObservingGraphics_(self, graphics):
61        if graphics is None: return
62        for graphic in graphics:
63            for key in graphic.class__().keysForNonBoundsProperties():
64                graphic.removeObserver_forKeyPath_(self, key)
65            graphic.removeObserver_forKeyPath_(self, u"drawingBounds")
66
67    def bind_toObject_withKeyPath_options_(self, bindingName, observableObject, observableKeyPath, options):
68        if bindingName == u"graphics":
69            self.graphicsContainer = observableObject
70            self.graphicsKeyPath = observableKeyPath
71            self.graphicsContainer.addObserver_forKeyPath_options_context_(
72                    self, self.graphicsKeyPath, (NSKeyValueObservingOptionNew |
73                    NSKeyValueObservingOptionOld), GraphicsObservationContext)
74            self.startObservingGraphics_(self.graphics())
75
76        elif bindingName == u"selectionIndexes":
77            self.selectionIndexesContainer = observableObject
78            self.selectionIndexesKeyPath = observableKeyPath
79            self.selectionIndexesContainer.addObserver_forKeyPath_options_context_(
80                self, self.selectionIndexesKeyPath, 0, SelectionIndexesObservationContext)
81        self.setNeedsDisplay_(True)
82
83    def unbind_(self, bindingName):
84        if bindingName == u"graphics":
85            self.graphicsContainer.removeObserver_forKeyPath_(self, self.graphicsKeyPath)
86            self.graphicsContainer = None
87            self.graphicsKeyPath = None
88        if bindingName == u"selectionIndexes":
89            self.selectionIndexesContainer.removeObserver_forKeyPath_(self, self.selectionIndexesKeyPath)
90            self.seletionIndexesContainer = None
91            self.selectionIndexesKeyPath = None
92        self.setNeedsDisplay_(True)
93
94    def observeValueForKeyPath_ofObject_change_context_(self, keyPath, object, change, context):
95        if context == GraphicsObservationContext:
96            # Should be able to use
97            # NSArray *oldGraphics = [change objectForKey:NSKeyValueChangeOldKey];
98            # etc. but the dictionary doesn't contain old and new arrays...??
99            newGraphics = Set(object.valueForKeyPath_(self.graphicsKeyPath))
100            onlyNew = newGraphics - Set(self.oldGraphics)
101            self.startObservingGraphics_(onlyNew)
102
103            if self.oldGraphics:
104                removed = Set(self.oldGraphics) - newGraphics
105                self.stopObservingGraphics_(removed)
106
107            self.oldGraphics = newGraphics
108
109            # could check drawingBounds of old and new, but...
110            self.setNeedsDisplay_(True)
111            return
112
113        if context == PropertyObservationContext:
114            updateRect = (0,)
115            # Note: for Circle, drawingBounds is a dependent key of all the other
116            # property keys except color, so we'll get this anyway...
117            if keyPath == u"drawingBounds":
118                newBounds = change.objectForKey_(NSKeyValueChangeNewKey)
119                oldBounds = change.objectForKey_(NSKeyValueChangeOldKey)
120                updateRect = NSUnionRect(newBounds, oldBounds)
121            else:
122                updateRect = object.drawingBounds()
123            updateRect = NSMakeRect(updateRect.origin.x-1.0,
124                                updateRect.origin.y-1.0,
125                                updateRect.size.width+2.0,
126                                updateRect.size.height+2.0)
127            self.setNeedsDisplay_(True)
128            return
129
130        if context == SelectionIndexesObservationContext:
131            self.setNeedsDisplay_(True)
132            return
133
134    def drawRect_(self, rect):
135        myBounds = self.bounds()
136        NSDrawLightBezel(myBounds, myBounds) # AppKit Function
137        clipRect = NSBezierPath.bezierPathWithRect_(NSInsetRect(myBounds, 2.0, 2.0))
138        clipRect.addClip()
139
140        # Draw graphics
141        graphicsArray = self.graphics()
142        if graphicsArray:
143            for graphic in graphicsArray:
144                graphicDrawingBounds = graphic.drawingBounds()
145                if NSIntersectsRect(rect, graphicDrawingBounds):
146                    graphic.drawInView_(self)
147
148        # Draw a red box around items in the current selection.
149        # Selection should be handled by the graphic, but this is a
150        # shortcut simply for display.
151
152        currentSelectionIndexes = self.selectionIndexes() # ist das wir ein Array im Indezes?
153        if currentSelectionIndexes != None:
154            path = NSBezierPath.bezierPath()
155            index = currentSelectionIndexes.firstIndex()
156            while index != NSNotFound:
157                graphicDrawingBounds = graphicsArray[index].drawingBounds()
158                if NSIntersectsRect(rect, graphicDrawingBounds):
159                    path.appendBezierPathWithRect_(graphicDrawingBounds)
160                index = currentSelectionIndexes.indexGreaterThanIndex_(index)
161
162            NSColor.redColor().set()
163            path.setLineWidth_(1.5)
164            path.stroke()
165
166
167        # Fairly simple just to illustrate the point
168    def mouseDown_(self, event):
169        # find out if we hit anything
170        p = self.convertPoint_fromView_(event.locationInWindow(), None)
171        for aGraphic in self.graphics():
172            if aGraphic.hitTest_isSelected_(p, False):
173                break; # aGraphic soll spaeter einen Wert haben, falls es getroffene gibt!
174        else:
175            aGraphic = None
176
177        # if no graphic hit, then if extending selection do nothing
178        # else set selection to nil
179        if aGraphic == None:
180            if not event.modifierFlags() & NSShiftKeyMask:
181                self.selectionIndexesContainer.setValue_forKeyPath_(None, self.selectionIndexesKeyPath)
182            return
183
184        # graphic hit
185        # if not extending selection (Shift key down) then set
186        # selection to this graphic
187        # if extending selection, then:
188        # - if graphic in selection remove it
189        # - if not in selection add it
190        graphicIndex = self.graphics().index(aGraphic)
191        if not event.modifierFlags() & NSShiftKeyMask:
192            selection = NSIndexSet.indexSetWithIndex_(graphicIndex)
193        else:
194            if  self.selectionIndexes().containsIndex_(graphicIndex):
195                selection = self.selectionIndexes().mutableCopy()
196                selection.removeIndex_(graphicIndex)
197            else:
198                selection = self.selectionIndexes().mutableCopy()
199                selection.addIndex_(graphicIndex)
200        self.selectionIndexesContainer.setValue_forKeyPath_(selection, self.selectionIndexesKeyPath)
201
202
203GraphicsView.exposeBinding_(u"graphics")
204GraphicsView.exposeBinding_(u"selectionIndexes")
205