• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10/pyobjc-45/2.5/pyobjc/pyobjc-framework-Cocoa/Examples/AppKit/CocoaBindings/Bookmarks/
1#
2#  DNDArrayController.py
3#  Bookmarks
4#
5#  Converted by u.fiedler on 10.02.05.
6#
7#  The original version was written in Objective-C by Malcolm Crawford
8#  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
9#
10#  See "Dragging Files" for a conceptual introduction:
11#  file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Conceptual/DragandDrop/index.html#//apple_ref/doc/uid/10000069i
12#  or http://developer.apple.com/documentation/Cocoa/Conceptual/DragandDrop/Tasks/DraggingFiles.html
13
14
15from Foundation import *
16from AppKit import *
17from BookmarksDocument import CopiedRowsType
18
19MovedRowsType = u"MOVED_ROWS_TYPE"
20
21class DNDArrayController (NSArrayController):
22    # DNDArrayController is delegate and dataSource of tableView
23    tableView = objc.IBOutlet()
24
25    def awakeFromNib(self):
26        "register for drag and drop"
27        self.tableView.registerForDraggedTypes_(
28            [CopiedRowsType, MovedRowsType, NSURLPboardType])
29        self.tableView.setAllowsMultipleSelection_(True)
30
31
32    def tableView_writeRows_toPasteboard_(self, tv, rows, pboard):
33        # declare our own pasteboard types
34        typesArray = [CopiedRowsType, MovedRowsType]
35
36        # If the number of rows is not 1, then we only support our own types.
37        # If there is just one row, then try to create an NSURL from the url
38        # value in that row.  If that's possible, add NSURLPboardType to the
39        # list of supported types, and add the NSURL to the pasteboard.
40        if len(rows) != 1:
41            pboard.declareTypes_owner_(typesArray, self)
42        else:
43            # Try to create an URL
44            # If we can, add NSURLPboardType to the declared types and write
45            # the URL to the pasteboard; otherwise declare existing types
46            row = rows[0]
47            urlString = self.arrangedObjects()[row].valueForKey_(u'url')
48            url = None
49            if urlString:
50                url = NSURL.URLWithString_(urlString)
51            if urlString and url:
52                typesArray.append(NSURLPboardType)
53                pboard.declareTypes_owner_(typesArray, self)
54                url.writeToPasteboard_(pboard)
55            else:
56                pboard.declareTypes_owner_(typesArray, self)
57
58        # add rows array for local move
59        pboard.setPropertyList_forType_(rows, MovedRowsType)
60
61        # create new array of selected rows for remote drop
62        # could do deferred provision, but keep it direct for clarity
63        rowCopies = self.arrangedObjects()[:]
64
65        # setPropertyList works here because we're using dictionaries, strings,
66        # and dates; otherwise, archive collection to NSData...
67        pboard.setPropertyList_forType_(rowCopies, CopiedRowsType)
68        return True
69
70    def tableView_validateDrop_proposedRow_proposedDropOperation_(self, tv, info, row, op):
71        dragOp = NSDragOperationCopy
72        # if drag source is self, it's a move
73        if info.draggingSource() == self.tableView:
74            dragOp =  NSDragOperationMove
75        # we want to put the object at, not over,
76        # the current row (contrast NSTableViewDropOn)
77        tv.setDropRow_dropOperation_(row, NSTableViewDropAbove)
78        return dragOp
79
80    def tableView_acceptDrop_row_dropOperation_(self, tv, info, row, op):
81        if row < 0:
82            row = 0
83        if info.draggingSource() == self.tableView:
84            rows = info.draggingPasteboard().propertyListForType_(MovedRowsType)
85            indexSet = self.indexSetFromRows_(rows)
86            self.moveObjectsInArrangedObjectsFromIndexes_toIndex_(indexSet, row)
87            # set selected rows to those that were just moved
88            # Need to work out what moved where to determine proper selection...
89            rowsAbove = self.rowsAboveRow_inIndexSet_(row, indexSet)
90            aRange = NSMakeRange(row - rowsAbove, indexSet.count())
91            indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange)
92            # set selected rows to those that were just copied
93            self.setSelectionIndexes_(indexSet)
94            return True
95
96        # Can we get rows from another document?  If so, add them, then return.
97        newRows = info.draggingPasteboard().propertyListForType_(CopiedRowsType)
98        if newRows:
99            aRange = NSMakeRange(row, newRows.count())
100            indexSet = NSIndexSet.indexSetWithIndexesInRange_(aRange)
101            self.insertObjects_atArrangedObjectIndexes_(newRows, indexSet)
102            self.setSelectionIndexes_(indexSet)
103            return True
104
105        # Can we get an URL?  If so, add a new row, configure it, then return.
106        url = NSURL.URLFromPasteboard_(info.draggingPasteboard())
107        if url:
108            newObject = self.newObject()
109            self.insertObject_atArrangedObjectIndex_(newObject, row)
110            newObject.setValue_forKey_(url.absoluteString(), u"url")
111            newObject.setValue_forKey_(NSCalendarDate.date(), u"date")
112            # set selected rows to those that were just copied
113            self.setSelectionIndex_(row)
114            return True
115        return False
116
117    def moveObjectsInArrangedObjectsFromIndexes_toIndex_(self, indexSet, insertIndex):
118        objects = self.arrangedObjects()
119        index = indexSet.lastIndex()
120        aboveInsertIndexCount = 0
121        removeIndex = 0
122
123        while index != NSNotFound:
124            if index >= insertIndex:
125                removeIndex = index + aboveInsertIndexCount
126                aboveInsertIndexCount += 1
127            else:
128                removeIndex = index
129                insertIndex -= 1
130            obj = objects.objectAtIndex_(removeIndex)
131            self.removeObjectAtArrangedObjectIndex_(removeIndex)
132            self.insertObject_atArrangedObjectIndex_(obj, insertIndex)
133            index = indexSet.indexLessThanIndex_(index)
134
135    def indexSetFromRows_(self, rows):
136        indexSet = NSMutableIndexSet.indexSet()
137        for row in rows:
138            indexSet.addIndex_(row)
139        return indexSet
140
141    def rowsAboveRow_inIndexSet_(self, row, indexSet):
142        currentIndex = indexSet.firstIndex()
143        i = 0
144        while currentIndex != NSNotFound:
145            if currentIndex < row:
146                i += 1
147            currentIndex = indexSet.indexGreaterThanIndex_(currentIndex)
148        return i
149