├── OutlineViewReorder.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── mattg.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── OutlineViewReorder.xcscheme
└── project.pbxproj
├── OutlineViewReorder
├── OutlineItemView.swift
├── AppDelegate.swift
├── TextFieldDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── OutlineDelegate.swift
├── Info.plist
├── ViewController.swift
├── TestData.swift
├── OutlineDataSource.swift
└── Base.lproj
│ └── Main.storyboard
└── README.md
/OutlineViewReorder.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/OutlineViewReorder/OutlineItemView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OutlineItemView.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class OutlineItemView: NSTableCellView {
12 | // Base class has text and image cells
13 | }
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NSOutlineViewReorder
2 | NSOutlineView Drag & Drop Reordering in Swift
3 |
4 | This is an example showing how two create a two level NSOutlineView with Drag & Drop reordering.
5 | I wanted to create an example that was as simple as possible so that it is a little more clear what is going on.
6 | The Apple example https://developer.apple.com/library/mac/samplecode/DragNDropOutlineView/Introduction/Intro.html
7 | is very complex and was written in Objective-C rather than Swift. (Still a work in progress, commenting code)
8 |
--------------------------------------------------------------------------------
/OutlineViewReorder.xcodeproj/xcuserdata/mattg.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | OutlineViewReorder.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | A9B89A321D0341BD000587EF
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/OutlineViewReorder/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool
15 | {
16 | return true
17 | }
18 |
19 | func applicationDidFinishLaunching(_ aNotification: Notification) {
20 | // Insert code here to initialize your application
21 | }
22 |
23 | func applicationWillTerminate(_ aNotification: Notification) {
24 | // Insert code here to tear down your application
25 | }
26 |
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/OutlineViewReorder/TextFieldDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TextFieldDelegate.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/6/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | extension ViewController: NSTextFieldDelegate {
12 | func controlTextDidEndEditing(_ obj: Notification) {
13 | //printDebug("text edit end \(obj.debugDescription)");
14 | let textField = obj.object as! NSTextField
15 | let row = theOutline.row(for: textField)
16 | let item = theOutline.item(atRow: row)
17 |
18 | let newName:String = textField.stringValue
19 |
20 | if let theItem = item as? BaseItem
21 | {
22 | theItem.name = newName
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/OutlineViewReorder/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/OutlineViewReorder/OutlineDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OutlineDelegate.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | extension ViewController: NSOutlineViewDelegate {
12 |
13 | func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? {
14 | let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "OutlineColItem"), owner: self) as! OutlineItemView
15 |
16 | cell.textField!.delegate = self
17 |
18 | if let folderItem = item as? FolderItem
19 | {
20 | cell.textField!.stringValue = folderItem.name
21 | cell.imageView!.image = folderImage
22 | }
23 | else if let aItem = item as? TestItem
24 | {
25 | cell.textField!.stringValue = aItem.name
26 | cell.imageView!.image = itemImage
27 | }
28 |
29 | return cell
30 | }
31 |
32 | // func outlineView(outlineView: NSOutlineView, shouldExpandItem item: AnyObject) -> Bool {
33 | // return (draggedNode == nil)
34 | // }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/OutlineViewReorder/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSHumanReadableCopyright
28 | Copyright © 2016 Kinematic Systems. All rights reserved.
29 | NSMainStoryboardFile
30 | Main
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/OutlineViewReorder/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class ViewController: NSViewController {
12 | @IBOutlet weak var theOutline: NSOutlineView!
13 | var folderImage = NSWorkspace.shared.icon(forFileType: NSFileTypeForHFSTypeCode(OSType(kGenericFolderIcon)))
14 | var itemImage = NSWorkspace.shared.icon(forFileType: NSFileTypeForHFSTypeCode(OSType(kGenericDocumentIcon)))
15 |
16 | var testData = TestData()
17 | var draggedNode:AnyObject? = nil
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | folderImage.size = NSSize(width: 16, height: 16)
22 | itemImage.size = NSSize(width: 16, height: 16)
23 |
24 | // Register for the dropped object types we can accept.
25 | theOutline.registerForDraggedTypes([REORDER_PASTEBOARD_TYPE])
26 |
27 | // Disable dragging items from our view to other applications.
28 | theOutline.setDraggingSourceOperationMask(NSDragOperation(), forLocal: false)
29 |
30 | // Enable dragging items within and into our view.
31 | theOutline.setDraggingSourceOperationMask(NSDragOperation.every, forLocal: true)
32 | }
33 |
34 | override var representedObject: Any? {
35 | didSet {
36 | // Update the view, if already loaded.
37 | }
38 | }
39 |
40 | @IBAction func undo(_ sender: AnyObject) {
41 | testData = TestData()
42 | theOutline.reloadData()
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/OutlineViewReorder/TestData.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestData.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class BaseItem {
12 | var name:String = ""
13 |
14 | func dump()
15 | {
16 | print(name)
17 | }
18 | }
19 |
20 | class TestItem: BaseItem {
21 | override func dump()
22 | {
23 | print("Item: ", terminator:"")
24 | super.dump()
25 | }
26 | }
27 |
28 | class FolderItem: BaseItem {
29 | var items:[TestItem] = []
30 |
31 | override func dump()
32 | {
33 | print("Folder: ", terminator:"")
34 | super.dump()
35 |
36 | for item in items
37 | {
38 | print(" ", terminator:"")
39 | item.dump()
40 | }
41 | }
42 | }
43 |
44 | class TestData
45 | {
46 | var items:[BaseItem] = []
47 |
48 | init() {
49 | for i in 1...5
50 | {
51 | let item = TestItem()
52 | item.name = "RootItem.\(i)"
53 | items.append(item)
54 | }
55 |
56 | for i in 1...5
57 | {
58 | let folder = FolderItem()
59 | folder.name = "Folder.\(i)"
60 | for j in 1...3
61 | {
62 | let item = TestItem()
63 | item.name = folder.name + ".Child.\(j)"
64 | folder.items.append(item)
65 | }
66 |
67 | items.append(folder)
68 | }
69 | let folder = FolderItem()
70 | folder.name = "Empty"
71 | items.append(folder)
72 | }
73 |
74 | // Moves the items in a way that is compatible with NSOutlineView's method of the same name
75 | func moveItemAtIndex(_ fromIndex: Int, inParent oldParent: FolderItem?, toIndex: Int, inParent newParent: FolderItem?)
76 | {
77 | var removedItem:BaseItem
78 | if oldParent == nil
79 | {
80 | removedItem = self.items.remove(at: fromIndex)
81 | }
82 | else
83 | {
84 | removedItem = oldParent!.items.remove(at: fromIndex)
85 | }
86 |
87 | if newParent == nil
88 | {
89 | self.items.insert(removedItem, at: toIndex)
90 | }
91 | else
92 | {
93 | newParent!.items.insert(removedItem as! TestItem, at: toIndex)
94 | }
95 |
96 | }
97 |
98 | func dump() {
99 | for item in items
100 | {
101 | item.dump()
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/OutlineViewReorder.xcodeproj/xcuserdata/mattg.xcuserdatad/xcschemes/OutlineViewReorder.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/OutlineViewReorder/OutlineDataSource.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OutlineDataSource.swift
3 | // OutlineViewReorder
4 | //
5 | // Created by Matt Grippaldi on 6/4/16.
6 | // Copyright © 2016 Kinematic Systems. All rights reserved.
7 | //
8 |
9 |
10 | import Cocoa
11 | let REORDER_PASTEBOARD_TYPE = NSPasteboard.PasteboardType(rawValue: "com.kinematicsystems.outline.item")
12 |
13 | extension ViewController: NSOutlineViewDataSource, NSPasteboardItemDataProvider {
14 |
15 | func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
16 |
17 | if item == nil
18 | {
19 | return testData.items.count
20 | }
21 | else if let folderItem = item as? FolderItem
22 | {
23 | return folderItem.items.count
24 | }
25 |
26 | return 0
27 | }
28 |
29 | func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
30 | if item == nil
31 | {
32 | return testData.items[index]
33 | }
34 | else if let folderItem = item as? FolderItem
35 | {
36 | return folderItem.items[index]
37 | }
38 |
39 | return "BAD ITEM"
40 | }
41 |
42 | func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool {
43 | return (item is FolderItem)
44 | }
45 |
46 |
47 | func outlineView(_ outlineView: NSOutlineView, objectValueFor objectValueForTableColumn: NSTableColumn?, byItem:Any?) -> Any? {
48 | if let item = byItem as? BaseItem
49 | {
50 | return item.name
51 | }
52 |
53 | return "???????"
54 | }
55 |
56 | // MARK: Drag & Drop
57 | func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
58 | let pbItem:NSPasteboardItem = NSPasteboardItem()
59 | pbItem.setDataProvider(self, forTypes: [REORDER_PASTEBOARD_TYPE])
60 | return pbItem
61 | }
62 |
63 | func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItems draggedItems: [Any]) {
64 | draggedNode = draggedItems[0] as AnyObject?
65 | session.draggingPasteboard.setData(Data(), forType: REORDER_PASTEBOARD_TYPE)
66 | }
67 |
68 | func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
69 | var retVal:NSDragOperation = NSDragOperation()
70 | var itemName = "nilItem"
71 |
72 | let baseItem = item as? BaseItem
73 |
74 | if baseItem != nil
75 | {
76 | itemName = baseItem!.name
77 | }
78 |
79 | // proposedItem is the item we are dropping on not the item we are dragging
80 | // - If dragging a set target item must be nil
81 | if (item as AnyObject? !== draggedNode && index != NSOutlineViewDropOnItemIndex)
82 | {
83 | if let _ = draggedNode as? FolderItem
84 | {
85 | if (item == nil)
86 | {
87 | retVal = NSDragOperation.generic
88 | }
89 | }
90 | else if let _ = draggedNode as? TestItem
91 | {
92 | retVal = NSDragOperation.generic
93 | }
94 | }
95 |
96 | debugPrint("validateDrop targetItem:\(itemName) childIndex:\(index) returning: \(retVal != NSDragOperation())")
97 | return retVal
98 | }
99 |
100 | func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
101 | var retVal:Bool = false
102 | if !(draggedNode is BaseItem)
103 | {
104 | return false
105 | }
106 |
107 | let srcItem = draggedNode as! BaseItem
108 | let destItem:FolderItem? = item as? FolderItem
109 | let parentItem:FolderItem? = outlineView.parent(forItem: srcItem) as? FolderItem
110 | let oldIndex = outlineView.childIndex(forItem: srcItem)
111 | var toIndex = index
112 |
113 | if destItem != nil && parentItem != nil
114 | {
115 | debugPrint("move src:\(srcItem.name) dest:\(destItem!.name) destIndex:\(index) oldIndex:\(oldIndex) srcParent:\(parentItem!.name) toIndex:\(toIndex) toParent:\(destItem!.name) childIndex:\(index)", terminator: "")
116 | }
117 | else
118 | {
119 | debugPrint("destination or parent is nil")
120 | }
121 |
122 | if (toIndex == NSOutlineViewDropOnItemIndex) // This should never happen, prevented in validateDrop
123 | {
124 | toIndex = 0
125 | }
126 | else if toIndex > oldIndex
127 | {
128 | toIndex -= 1
129 | }
130 |
131 | if srcItem is FolderItem && destItem != nil
132 | {
133 | retVal = false
134 | }
135 | else if oldIndex != toIndex || parentItem !== destItem
136 | {
137 | testData.moveItemAtIndex(oldIndex, inParent: parentItem, toIndex: toIndex, inParent: destItem)
138 | outlineView.moveItem(at: oldIndex, inParent: parentItem, to: toIndex, inParent: destItem)
139 | retVal = true
140 | }
141 |
142 | debugPrint(" returning:\(retVal)")
143 | if retVal
144 | {
145 | testData.dump()
146 | }
147 | return retVal
148 | }
149 |
150 | func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
151 | //debugPrint("Drag session ended")
152 | self.draggedNode = nil
153 | }
154 |
155 |
156 | // MARK: NSPasteboardItemDataProvider
157 | func pasteboard(_ pasteboard: NSPasteboard?, item: NSPasteboardItem, provideDataForType type: NSPasteboard.PasteboardType) {
158 | let s = "Outline Pasteboard Item"
159 | item.setString(s, forType: type)
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/OutlineViewReorder.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A9B89A371D0341BD000587EF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A361D0341BD000587EF /* AppDelegate.swift */; };
11 | A9B89A391D0341BD000587EF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A381D0341BD000587EF /* ViewController.swift */; };
12 | A9B89A3B1D0341BD000587EF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A9B89A3A1D0341BD000587EF /* Assets.xcassets */; };
13 | A9B89A3E1D0341BD000587EF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A9B89A3C1D0341BD000587EF /* Main.storyboard */; };
14 | A9B89A461D034354000587EF /* OutlineDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A451D034354000587EF /* OutlineDataSource.swift */; };
15 | A9B89A481D034363000587EF /* OutlineDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A471D034363000587EF /* OutlineDelegate.swift */; };
16 | A9B89A4A1D034498000587EF /* TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A491D034498000587EF /* TestData.swift */; };
17 | A9B89A4E1D038CDB000587EF /* OutlineItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A4D1D038CDB000587EF /* OutlineItemView.swift */; };
18 | A9B89A541D05D883000587EF /* TextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B89A531D05D883000587EF /* TextFieldDelegate.swift */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXFileReference section */
22 | A9B89A331D0341BD000587EF /* OutlineViewReorder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OutlineViewReorder.app; sourceTree = BUILT_PRODUCTS_DIR; };
23 | A9B89A361D0341BD000587EF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
24 | A9B89A381D0341BD000587EF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
25 | A9B89A3A1D0341BD000587EF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
26 | A9B89A3D1D0341BD000587EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
27 | A9B89A3F1D0341BD000587EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
28 | A9B89A451D034354000587EF /* OutlineDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineDataSource.swift; sourceTree = ""; };
29 | A9B89A471D034363000587EF /* OutlineDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineDelegate.swift; sourceTree = ""; };
30 | A9B89A491D034498000587EF /* TestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestData.swift; sourceTree = ""; };
31 | A9B89A4D1D038CDB000587EF /* OutlineItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutlineItemView.swift; sourceTree = ""; };
32 | A9B89A531D05D883000587EF /* TextFieldDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldDelegate.swift; sourceTree = ""; };
33 | /* End PBXFileReference section */
34 |
35 | /* Begin PBXFrameworksBuildPhase section */
36 | A9B89A301D0341BD000587EF /* Frameworks */ = {
37 | isa = PBXFrameworksBuildPhase;
38 | buildActionMask = 2147483647;
39 | files = (
40 | );
41 | runOnlyForDeploymentPostprocessing = 0;
42 | };
43 | /* End PBXFrameworksBuildPhase section */
44 |
45 | /* Begin PBXGroup section */
46 | A9B89A2A1D0341BD000587EF = {
47 | isa = PBXGroup;
48 | children = (
49 | A9B89A351D0341BD000587EF /* OutlineViewReorder */,
50 | A9B89A341D0341BD000587EF /* Products */,
51 | );
52 | sourceTree = "";
53 | };
54 | A9B89A341D0341BD000587EF /* Products */ = {
55 | isa = PBXGroup;
56 | children = (
57 | A9B89A331D0341BD000587EF /* OutlineViewReorder.app */,
58 | );
59 | name = Products;
60 | sourceTree = "";
61 | };
62 | A9B89A351D0341BD000587EF /* OutlineViewReorder */ = {
63 | isa = PBXGroup;
64 | children = (
65 | A9B89A361D0341BD000587EF /* AppDelegate.swift */,
66 | A9B89A381D0341BD000587EF /* ViewController.swift */,
67 | A9B89A451D034354000587EF /* OutlineDataSource.swift */,
68 | A9B89A471D034363000587EF /* OutlineDelegate.swift */,
69 | A9B89A4D1D038CDB000587EF /* OutlineItemView.swift */,
70 | A9B89A531D05D883000587EF /* TextFieldDelegate.swift */,
71 | A9B89A491D034498000587EF /* TestData.swift */,
72 | A9B89A3A1D0341BD000587EF /* Assets.xcassets */,
73 | A9B89A3C1D0341BD000587EF /* Main.storyboard */,
74 | A9B89A3F1D0341BD000587EF /* Info.plist */,
75 | );
76 | path = OutlineViewReorder;
77 | sourceTree = "";
78 | };
79 | /* End PBXGroup section */
80 |
81 | /* Begin PBXNativeTarget section */
82 | A9B89A321D0341BD000587EF /* OutlineViewReorder */ = {
83 | isa = PBXNativeTarget;
84 | buildConfigurationList = A9B89A421D0341BD000587EF /* Build configuration list for PBXNativeTarget "OutlineViewReorder" */;
85 | buildPhases = (
86 | A9B89A2F1D0341BD000587EF /* Sources */,
87 | A9B89A301D0341BD000587EF /* Frameworks */,
88 | A9B89A311D0341BD000587EF /* Resources */,
89 | );
90 | buildRules = (
91 | );
92 | dependencies = (
93 | );
94 | name = OutlineViewReorder;
95 | productName = OutlineViewReorder;
96 | productReference = A9B89A331D0341BD000587EF /* OutlineViewReorder.app */;
97 | productType = "com.apple.product-type.application";
98 | };
99 | /* End PBXNativeTarget section */
100 |
101 | /* Begin PBXProject section */
102 | A9B89A2B1D0341BD000587EF /* Project object */ = {
103 | isa = PBXProject;
104 | attributes = {
105 | LastSwiftUpdateCheck = 0730;
106 | LastUpgradeCheck = 1340;
107 | ORGANIZATIONNAME = "Kinematic Systems";
108 | TargetAttributes = {
109 | A9B89A321D0341BD000587EF = {
110 | CreatedOnToolsVersion = 7.3;
111 | LastSwiftMigration = 0820;
112 | };
113 | };
114 | };
115 | buildConfigurationList = A9B89A2E1D0341BD000587EF /* Build configuration list for PBXProject "OutlineViewReorder" */;
116 | compatibilityVersion = "Xcode 3.2";
117 | developmentRegion = en;
118 | hasScannedForEncodings = 0;
119 | knownRegions = (
120 | en,
121 | Base,
122 | );
123 | mainGroup = A9B89A2A1D0341BD000587EF;
124 | productRefGroup = A9B89A341D0341BD000587EF /* Products */;
125 | projectDirPath = "";
126 | projectRoot = "";
127 | targets = (
128 | A9B89A321D0341BD000587EF /* OutlineViewReorder */,
129 | );
130 | };
131 | /* End PBXProject section */
132 |
133 | /* Begin PBXResourcesBuildPhase section */
134 | A9B89A311D0341BD000587EF /* Resources */ = {
135 | isa = PBXResourcesBuildPhase;
136 | buildActionMask = 2147483647;
137 | files = (
138 | A9B89A3B1D0341BD000587EF /* Assets.xcassets in Resources */,
139 | A9B89A3E1D0341BD000587EF /* Main.storyboard in Resources */,
140 | );
141 | runOnlyForDeploymentPostprocessing = 0;
142 | };
143 | /* End PBXResourcesBuildPhase section */
144 |
145 | /* Begin PBXSourcesBuildPhase section */
146 | A9B89A2F1D0341BD000587EF /* Sources */ = {
147 | isa = PBXSourcesBuildPhase;
148 | buildActionMask = 2147483647;
149 | files = (
150 | A9B89A391D0341BD000587EF /* ViewController.swift in Sources */,
151 | A9B89A461D034354000587EF /* OutlineDataSource.swift in Sources */,
152 | A9B89A4E1D038CDB000587EF /* OutlineItemView.swift in Sources */,
153 | A9B89A541D05D883000587EF /* TextFieldDelegate.swift in Sources */,
154 | A9B89A371D0341BD000587EF /* AppDelegate.swift in Sources */,
155 | A9B89A4A1D034498000587EF /* TestData.swift in Sources */,
156 | A9B89A481D034363000587EF /* OutlineDelegate.swift in Sources */,
157 | );
158 | runOnlyForDeploymentPostprocessing = 0;
159 | };
160 | /* End PBXSourcesBuildPhase section */
161 |
162 | /* Begin PBXVariantGroup section */
163 | A9B89A3C1D0341BD000587EF /* Main.storyboard */ = {
164 | isa = PBXVariantGroup;
165 | children = (
166 | A9B89A3D1D0341BD000587EF /* Base */,
167 | );
168 | name = Main.storyboard;
169 | sourceTree = "";
170 | };
171 | /* End PBXVariantGroup section */
172 |
173 | /* Begin XCBuildConfiguration section */
174 | A9B89A401D0341BD000587EF /* Debug */ = {
175 | isa = XCBuildConfiguration;
176 | buildSettings = {
177 | ALWAYS_SEARCH_USER_PATHS = NO;
178 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
179 | CLANG_ANALYZER_NONNULL = YES;
180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
181 | CLANG_CXX_LIBRARY = "libc++";
182 | CLANG_ENABLE_MODULES = YES;
183 | CLANG_ENABLE_OBJC_ARC = YES;
184 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
185 | CLANG_WARN_BOOL_CONVERSION = YES;
186 | CLANG_WARN_COMMA = YES;
187 | CLANG_WARN_CONSTANT_CONVERSION = YES;
188 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
189 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
190 | CLANG_WARN_EMPTY_BODY = YES;
191 | CLANG_WARN_ENUM_CONVERSION = YES;
192 | CLANG_WARN_INFINITE_RECURSION = YES;
193 | CLANG_WARN_INT_CONVERSION = YES;
194 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
195 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
196 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
197 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
198 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
199 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
200 | CLANG_WARN_STRICT_PROTOTYPES = YES;
201 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
202 | CLANG_WARN_UNREACHABLE_CODE = YES;
203 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
204 | CODE_SIGN_IDENTITY = "-";
205 | COPY_PHASE_STRIP = NO;
206 | DEBUG_INFORMATION_FORMAT = dwarf;
207 | ENABLE_STRICT_OBJC_MSGSEND = YES;
208 | ENABLE_TESTABILITY = YES;
209 | GCC_C_LANGUAGE_STANDARD = gnu99;
210 | GCC_DYNAMIC_NO_PIC = NO;
211 | GCC_NO_COMMON_BLOCKS = YES;
212 | GCC_OPTIMIZATION_LEVEL = 0;
213 | GCC_PREPROCESSOR_DEFINITIONS = (
214 | "DEBUG=1",
215 | "$(inherited)",
216 | );
217 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
218 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
219 | GCC_WARN_UNDECLARED_SELECTOR = YES;
220 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
221 | GCC_WARN_UNUSED_FUNCTION = YES;
222 | GCC_WARN_UNUSED_VARIABLE = YES;
223 | MACOSX_DEPLOYMENT_TARGET = 10.11;
224 | MTL_ENABLE_DEBUG_INFO = YES;
225 | ONLY_ACTIVE_ARCH = YES;
226 | SDKROOT = macosx;
227 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
228 | };
229 | name = Debug;
230 | };
231 | A9B89A411D0341BD000587EF /* Release */ = {
232 | isa = XCBuildConfiguration;
233 | buildSettings = {
234 | ALWAYS_SEARCH_USER_PATHS = NO;
235 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
236 | CLANG_ANALYZER_NONNULL = YES;
237 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
238 | CLANG_CXX_LIBRARY = "libc++";
239 | CLANG_ENABLE_MODULES = YES;
240 | CLANG_ENABLE_OBJC_ARC = YES;
241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
242 | CLANG_WARN_BOOL_CONVERSION = YES;
243 | CLANG_WARN_COMMA = YES;
244 | CLANG_WARN_CONSTANT_CONVERSION = YES;
245 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
247 | CLANG_WARN_EMPTY_BODY = YES;
248 | CLANG_WARN_ENUM_CONVERSION = YES;
249 | CLANG_WARN_INFINITE_RECURSION = YES;
250 | CLANG_WARN_INT_CONVERSION = YES;
251 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
252 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
253 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
255 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
256 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
257 | CLANG_WARN_STRICT_PROTOTYPES = YES;
258 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
259 | CLANG_WARN_UNREACHABLE_CODE = YES;
260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
261 | CODE_SIGN_IDENTITY = "-";
262 | COPY_PHASE_STRIP = NO;
263 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
264 | ENABLE_NS_ASSERTIONS = NO;
265 | ENABLE_STRICT_OBJC_MSGSEND = YES;
266 | GCC_C_LANGUAGE_STANDARD = gnu99;
267 | GCC_NO_COMMON_BLOCKS = YES;
268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
269 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
270 | GCC_WARN_UNDECLARED_SELECTOR = YES;
271 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
272 | GCC_WARN_UNUSED_FUNCTION = YES;
273 | GCC_WARN_UNUSED_VARIABLE = YES;
274 | MACOSX_DEPLOYMENT_TARGET = 10.11;
275 | MTL_ENABLE_DEBUG_INFO = NO;
276 | SDKROOT = macosx;
277 | SWIFT_COMPILATION_MODE = wholemodule;
278 | };
279 | name = Release;
280 | };
281 | A9B89A431D0341BD000587EF /* Debug */ = {
282 | isa = XCBuildConfiguration;
283 | buildSettings = {
284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
285 | CODE_SIGN_IDENTITY = "-";
286 | COMBINE_HIDPI_IMAGES = YES;
287 | INFOPLIST_FILE = OutlineViewReorder/Info.plist;
288 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
289 | PRODUCT_BUNDLE_IDENTIFIER = com.kinematicsystems.OutlineViewReorder;
290 | PRODUCT_NAME = "$(TARGET_NAME)";
291 | SWIFT_VERSION = 5.0;
292 | };
293 | name = Debug;
294 | };
295 | A9B89A441D0341BD000587EF /* Release */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
299 | CODE_SIGN_IDENTITY = "-";
300 | COMBINE_HIDPI_IMAGES = YES;
301 | INFOPLIST_FILE = OutlineViewReorder/Info.plist;
302 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
303 | PRODUCT_BUNDLE_IDENTIFIER = com.kinematicsystems.OutlineViewReorder;
304 | PRODUCT_NAME = "$(TARGET_NAME)";
305 | SWIFT_VERSION = 5.0;
306 | };
307 | name = Release;
308 | };
309 | /* End XCBuildConfiguration section */
310 |
311 | /* Begin XCConfigurationList section */
312 | A9B89A2E1D0341BD000587EF /* Build configuration list for PBXProject "OutlineViewReorder" */ = {
313 | isa = XCConfigurationList;
314 | buildConfigurations = (
315 | A9B89A401D0341BD000587EF /* Debug */,
316 | A9B89A411D0341BD000587EF /* Release */,
317 | );
318 | defaultConfigurationIsVisible = 0;
319 | defaultConfigurationName = Release;
320 | };
321 | A9B89A421D0341BD000587EF /* Build configuration list for PBXNativeTarget "OutlineViewReorder" */ = {
322 | isa = XCConfigurationList;
323 | buildConfigurations = (
324 | A9B89A431D0341BD000587EF /* Debug */,
325 | A9B89A441D0341BD000587EF /* Release */,
326 | );
327 | defaultConfigurationIsVisible = 0;
328 | defaultConfigurationName = Release;
329 | };
330 | /* End XCConfigurationList section */
331 | };
332 | rootObject = A9B89A2B1D0341BD000587EF /* Project object */;
333 | }
334 |
--------------------------------------------------------------------------------
/OutlineViewReorder/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
--------------------------------------------------------------------------------