diff --git a/AVRsack/ASProjDoc.swift b/AVRsack/ASProjDoc.swift
index 270ab98..6de436c 100644
--- a/AVRsack/ASProjDoc.swift
+++ b/AVRsack/ASProjDoc.swift
@@ -26,7 +26,7 @@ func pushToFront(inout list: [String], front: String) {
list.insert(front, atIndex: 0)
}
-class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
+class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate, NSOpenSavePanelDelegate {
@IBOutlet weak var editor : ACEView!
@IBOutlet weak var outline : NSOutlineView!
@IBOutlet weak var boardTool: NSPopUpButton!
@@ -262,11 +262,24 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
let selectedIndexes = NSIndexSet(index: outline.rowForItem(selection))
outline.selectRowIndexes(selectedIndexes, byExtendingSelection: false)
}
+ func selectedFiles() -> [ASFileItem] {
+ var selection = [ASFileItem]()
+ outline.selectedRowIndexes.enumerateIndexesUsingBlock() { (index, stop) in
+ if let file = self.outline.itemAtRow(index) as? ASFileItem {
+ selection.append(file)
+ }
+ }
+ return selection
+ }
// MARK: Outline View Delegate
func outlineViewSelectionDidChange(notification: NSNotification) {
- selectNode(outline.itemAtRow(outline.selectedRow) as ASFileNode?)
+ willChangeValueForKey("hasSelection")
+ if outline.numberOfSelectedRows < 2 {
+ selectNode(outline.itemAtRow(outline.selectedRow) as ASFileNode?)
+ }
+ didChangeValueForKey("hasSelection")
}
func outlineViewItemDidExpand(notification: NSNotification) {
let group = notification.userInfo!["NSObject"] as ASFileGroup
@@ -291,7 +304,92 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate {
}
}
}
-
+
+ // MARK: File manipulation
+
+ @IBAction func delete(AnyObject) {
+ let selection = selectedFiles()
+ var name : String
+ var ref : String
+ if selection.count == 1 {
+ name = "file “\(selection[0].url.lastPathComponent)”"
+ ref = "reference to it"
+ } else {
+ name = "\(selection.count) selected files"
+ ref = "references to them"
+ }
+ let alert = NSAlert()
+ alert.messageText =
+ "Do you want to move the \(name) to the Trash, or only remove the \(ref)?"
+ alert.addButtonWithTitle("Move to Trash")
+ alert.addButtonWithTitle(selection.count == 1 ? "Remove Reference" : "Remove References")
+ alert.addButtonWithTitle("Cancel")
+ (alert.buttons[0] as NSButton).keyEquivalent = ""
+ (alert.buttons[1] as NSButton).keyEquivalent = "\r"
+ alert.beginSheetModalForWindow(outline.window!) { (response) in
+ if response != NSAlertThirdButtonReturn {
+ if response == NSAlertFirstButtonReturn {
+ NSWorkspace.sharedWorkspace().recycleURLs(selection.map {$0.url}, completionHandler:nil)
+ }
+ self.files.apply { (node) in
+ if let group = node as? ASFileGroup {
+ for file in selection {
+ for (groupIdx, groupItem) in enumerate(group.children) {
+ if file as ASFileNode === groupItem {
+ group.children.removeAtIndex(groupIdx)
+ break
+ }
+ }
+ }
+ }
+ }
+ self.outline.deselectAll(self)
+ self.outline.reloadData()
+ self.updateChangeCount(.ChangeDone)
+ }
+ }
+ }
+
+ @IBAction func add(AnyObject) {
+ let panel = NSOpenPanel()
+ panel.canChooseFiles = true
+ panel.canChooseDirectories = false
+ panel.allowsMultipleSelection = true
+ panel.allowedFileTypes = ["h", "hpp", "hh", "c", "cxx", "c++", "cpp", "cc", "ino", "s", "md"]
+ panel.delegate = self
+ panel.beginSheetModalForWindow(outline.window!, completionHandler: { (returnCode: Int) -> Void in
+ if returnCode == NSFileHandlingPanelOKButton {
+ for url in panel.URLs as [NSURL] {
+ self.files.addFileURL(url)
+ }
+ self.outline.deselectAll(self)
+ self.outline.reloadData()
+ self.updateChangeCount(.ChangeDone)
+ }
+ })
+
+ }
+
+ func panel(panel:NSSavePanel, shouldEnableURL url:NSURL) -> Bool {
+ var shouldEnable = true
+ var resourceID : AnyObject?
+ url.getResourceValue(&resourceID, forKey:NSURLFileResourceIdentifierKey, error:nil)
+ files.apply {(node) in
+ if let file = node as? ASFileItem {
+ var thisID : AnyObject?
+ file.url.getResourceValue(&thisID, forKey:NSURLFileResourceIdentifierKey, error:nil)
+ if thisID != nil && resourceID!.isEqual(thisID!) {
+ shouldEnable = false
+ }
+ }
+ }
+ return shouldEnable
+ }
+
+ var hasSelection : Bool {
+ return selectedFiles().count > 0
+ }
+
// MARK: Editor configuration
@IBAction func changeTheme(item: NSMenuItem) {
diff --git a/AVRsack/Base.lproj/ASProjDoc.xib b/AVRsack/Base.lproj/ASProjDoc.xib
index e2a965f..b58bef3 100644
--- a/AVRsack/Base.lproj/ASProjDoc.xib
+++ b/AVRsack/Base.lproj/ASProjDoc.xib
@@ -19,64 +19,110 @@
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
-
+
@@ -224,7 +270,7 @@
-
+
diff --git a/AVRsack/Base.lproj/MainMenu.xib b/AVRsack/Base.lproj/MainMenu.xib
index 9d43f1c..b07b68b 100644
--- a/AVRsack/Base.lproj/MainMenu.xib
+++ b/AVRsack/Base.lproj/MainMenu.xib
@@ -192,7 +192,9 @@