Ver Fonte

【书签】toolbarItem 添加与实现

lizhe há 1 ano atrás
pai
commit
338fb3b473

+ 396 - 416
PDF Office/PDF Master/Class/PDFTools/KMBookmark/Controller/KMBookmarkController.swift

@@ -130,32 +130,32 @@ class KMBookmarkController: NSWindowController {
 //    }
 //    
 //    //MARK: Bookmarks support
-//    func getInsertionFolder(_ bookmarkPtr: inout SKBookmark?, childIndex indexPtr: inout UInt) {
-//        let rowIndex = outlineView.clickedRow
-//        var indexes = outlineView.selectedRowIndexes
-//        if rowIndex != -1 && !indexes.contains(rowIndex) {
-//            indexes = IndexSet(integer: rowIndex)
-//        }
-//        let rowIdx = indexes.last ?? NSNotFound
-//        
-//        var item = bookmarkRoot
-//        var idx = bookmarkRoot.countOfChildren
-//        
-//        if rowIdx != NSNotFound {
-//            if let selectedItem = outlineView.item(atRow: rowIdx) as? SKBookmark {
-//                if outlineView.isItemExpanded(selectedItem) {
-//                    item = selectedItem
-//                    idx = item.countOfChildren
-//                } else if let parent = selectedItem.parent, let itemIdx = parent.children.index(of: selectedItem) {
-//                    item = parent
-//                    idx = itemIdx + 1
-//                }
-//            }
-//        }
-//        
-//        bookmarkPtr = item
-//        indexPtr = idx
-//    }
+    func getInsertionFolder(_ bookmarkPtr: inout KMBookmark?, childIndex indexPtr: inout UInt) {
+        let rowIndex = outlineView.clickedRow
+        var indexes = outlineView.selectedRowIndexes
+        if rowIndex != -1 && !indexes.contains(rowIndex) {
+            indexes = IndexSet(integer: rowIndex)
+        }
+        let rowIdx = indexes.last ?? NSNotFound
+        
+        var item = KMBookmarkManager.manager.rootBookmark
+        var idx = item.children.count
+        
+        if rowIdx != NSNotFound {
+            if let selectedItem = outlineView.item(atRow: rowIdx) as? KMBookmark {
+                if outlineView.isItemExpanded(selectedItem) {
+                    item = selectedItem as! KMRootBookmark
+                    idx = item.children.count
+                } else if let parent = selectedItem.parent, let itemIdx = parent.children.firstIndex(of: selectedItem) {
+                    item = parent as! KMRootBookmark
+                    idx = itemIdx + 1
+                }
+            }
+        }
+        
+        bookmarkPtr = item
+        indexPtr = UInt(idx)
+    }
 //
 //    @IBAction func openBookmark(_ sender: Any) {
 //        if let bookmark = (sender as AnyObject).representedObject as? SKBookmark {
@@ -170,33 +170,40 @@ class KMBookmarkController: NSWindowController {
 //            bm.open()
 //        }
 //    }
-//
-//    @IBAction func insertBookmarkFolder(_ sender: Any) {
-//        let folder = SKBookmark.bookmarkFolder(withLabel: NSLocalizedString("Folder", comment: "default folder name"))
-//        var item: SKBookmark?
-//        var idx: UInt = 0
-//        
-//        getInsertionFolder(&item, childIndex: &idx)
-//        item?.insertObject(folder, inChildrenAtIndex: idx)
-//        
-//        if let row = outlineView.row(forItem: folder) {
-//            outlineView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
-//            outlineView.editColumn(0, row: row, with: nil, select: true)
-//        }
-//    }
-//
-//    @IBAction func insertBookmarkSeparator(_ sender: Any) {
-//        let separator = SKBookmark.bookmarkSeparator()
-//        var item: SKBookmark?
-//        var idx: UInt = 0
-//        
-//        getInsertionFolder(&item, childIndex: &idx)
-//        item?.insertObject(separator, inChildrenAtIndex: idx)
-//        
-//        if let row = outlineView.row(forItem: separator) {
-//            outlineView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
-//        }
-//    }
+
+    
+    func deleteBookmarks(bookmarks: [KMBookmark]) {
+        for item in minimumCoverForBookmarks(bookmarks).reversed() {
+            guard let parent = item.parent, let itemIndex = parent.children.firstIndex(of: item) else { continue }
+            parent.removeObjectFromChildren(index: itemIndex)
+        }
+    }
+    
+    
+    @IBAction func insertBookmarkFolder(_ sender: Any) {
+        let folder = KMFolderBookmark.folderBookmark(label: NSLocalizedString("Folder", comment: "default folder name"))
+        var item: KMBookmark?
+        var idx: UInt = 0
+        
+        getInsertionFolder(&item, childIndex: &idx)
+        item?.insert(child: folder, atIndex: idx)
+        
+        let row = outlineView.row(forItem: folder)
+        outlineView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
+        outlineView.editColumn(0, row: row, with: nil, select: true)
+    }
+
+    @IBAction func insertBookmarkSeparator(_ sender: Any) {
+        let separator = KMSeparatorBookmark()
+        var item: KMBookmark?
+        var idx: UInt = 0
+        
+        getInsertionFolder(&item, childIndex: &idx)
+        item?.insert(child: separator, atIndex: idx)
+        
+        let row = outlineView.row(forItem: separator)
+        outlineView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false)
+    }
 //
 //    @IBAction func addBookmark(_ sender: Any) {
 //        let openPanel = NSOpenPanel()
@@ -228,9 +235,9 @@ class KMBookmarkController: NSWindowController {
 //        }
 //    }
 //
-//    @IBAction func deleteBookmark(_ sender: Any) {
-//        outlineView.delete(sender)
-//    }
+    @IBAction func deleteBookmark(_ sender: Any) {
+        self.deleteBookmarks(bookmarks: [])
+    }
 //
 //    @IBAction func toggleStatusBar(_ sender: Any) {
 //        UserDefaults.standard.set(!statusBar.isVisible, forKey: SKShowBookmarkStatusBarKey)
@@ -249,7 +256,6 @@ class KMBookmarkController: NSWindowController {
 //
 //    @IBAction func deleteBookmarks(_ sender: Any) {
 //        guard let items = clickedBookmarks() as? [SKBookmark] else { return }
-//        endEditing()
 //        for item in items.reversed() {
 //            if let parent = item.parent, let itemIndex = parent.children.index(of: item) {
 //                parent.removeObject(fromChildrenAtIndex: itemIndex)
@@ -348,300 +354,6 @@ class KMBookmarkController: NSWindowController {
 //
 //    // avoid rebuilding the bookmarks menu on every key event
 //    func menuHasKeyEquivalent(_ menu: NSMenu, for event: NSEvent, target: AutoreleasingUnsafeMutablePointer<AnyObject?>?, action: UnsafeMutablePointer<Selector?>?) -> Bool { false }
-//
-//    
-//    // MARK: - NSOutlineView datasource methods
-//    func minimumCoverForBookmarks(_ items: [SKBookmark]) -> [SKBookmark] {
-//        var lastBm: SKBookmark?
-//        var minimalCover = [SKBookmark]()
-//        
-//        for bm in items {
-//            if !(bm.isDescendant(of: lastBm)) {
-//                minimalCover.append(bm)
-//                lastBm = bm
-//            }
-//        }
-//        return minimalCover
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
-//        let bookmark = item as? SKBookmark ?? bookmarkRoot
-//        return bookmark.bookmarkType == .folder ? bookmark.countOfChildren : 0
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, isItemExpandable item: Any) -> Bool {
-//        let bookmark = item as! SKBookmark
-//        return bookmark.bookmarkType == .folder
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
-//        let bookmark = (item as? SKBookmark) ?? bookmarkRoot
-//        return bookmark.objectInChildren(at: index)!
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, objectValueFor tableColumn: NSTableColumn?, byItem item: Any?) -> Any? {
-//        guard let column = tableColumn, let tcID = column.identifier else { return nil }
-//        guard let bm = item as? SKBookmark else { return nil }
-//        
-//        switch tcID {
-//        case LABEL_COLUMNID:
-//            return [SKTextWithIconStringKey: bm.label, SKTextWithIconImageKey: bm.icon]
-//        case FILE_COLUMNID:
-//            if bm.bookmarkType == .folder || bm.bookmarkType == .session {
-//                let count = bm.countOfChildren
-//                return count == 1 ? NSLocalizedString("1 item", comment: "Bookmark folder description") : String.localizedStringWithFormat(NSLocalizedString("%ld items", comment: "Bookmark folder description"), count)
-//            } else {
-//                return bm.fileURL?.path ?? ""
-//            }
-//        case PAGE_COLUMNID:
-//            return bm.pageNumber
-//        default:
-//            return nil
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, byItem item: Any?) {
-//        guard let column = tableColumn, let tcID = column.identifier else { return }
-//        guard let bm = item as? SKBookmark else { return }
-//        
-//        switch tcID {
-//        case LABEL_COLUMNID:
-//            if let newLabel = (object as? [String: Any])?[SKTextWithIconStringKey] as? String, newLabel != bm.label {
-//                bm.label = newLabel
-//            }
-//        case PAGE_COLUMNID:
-//            if let newPageNumber = object as? Int, newPageNumber != bm.pageNumber {
-//                bm.pageNumber = newPageNumber
-//            }
-//        default:
-//            break
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, writeItems items: [Any], to pboard: NSPasteboard) -> Bool {
-//        draggedBookmarks = minimumCoverForBookmarks(items as! [SKBookmark])
-//        pboard.clearContents()
-//        pboard.setData(Data(), forType: SKPasteboardTypeBookmarkRows)
-//        return true
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
-//        guard index != NSOutlineViewDropOnItemIndex else { return .none }
-//        guard let pboard = info.draggingPasteboard else { return .none }
-//        
-//        if pboard.canReadItem(withDataConformingToTypes: [SKPasteboardTypeBookmarkRows]) && info.draggingSource as? NSOutlineView == ov {
-//            return .move
-//        } else if NSURL.canReadFileURL(from: pboard) {
-//            return .every
-//        }
-//        return .none
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
-//        guard let pboard = info.draggingPasteboard else { return false }
-//        
-//        if pboard.canReadItem(withDataConformingToTypes: [SKPasteboardTypeBookmarkRows]) && info.draggingSource as? NSOutlineView == ov {
-//            var movedBookmarks = [SKBookmark]()
-//            var indexes = IndexSet()
-//            var insertionIndex = index
-//            
-//            let targetItem = item as? SKBookmark ?? bookmarkRoot
-//            
-//            endEditing()
-//            for bookmark in draggedBookmarks {
-//                guard let parent = bookmark.parent else { continue }
-//                guard let bookmarkIndex = parent.children.firstIndex(of: bookmark) else { continue }
-//                
-//                if targetItem == parent {
-//                    if insertionIndex > bookmarkIndex {
-//                        insertionIndex -= 1
-//                    }
-//                    if insertionIndex == bookmarkIndex {
-//                        continue
-//                    }
-//                }
-//                parent.removeObjectFromChildren(at: bookmarkIndex)
-//                targetItem.insertObject(bookmark, inChildrenAtIndex: insertionIndex)
-//                movedBookmarks.append(bookmark)
-//                insertionIndex += 1
-//            }
-//            
-//            for bookmark in movedBookmarks {
-//                let row = ov.row(forItem: bookmark)
-//                if row != -1 {
-//                    indexes.insert(row)
-//                }
-//            }
-//            if !indexes.isEmpty {
-//                ov.selectRowIndexes(indexes, byExtendingSelection: false)
-//            }
-//            return true
-//        } else {
-//            guard let urls = NSURL.readFileURLs(from: pboard) else { return false }
-//            
-//            let newBookmarks = SKBookmark.bookmarks(for: urls)
-//            if !newBookmarks.isEmpty {
-//                endEditing()
-//                let indexes = IndexSet(integersIn: index..<(index + newBookmarks.count))
-//                (item as? SKBookmark ?? bookmarkRoot).mutableArrayValue(forKey: "children").insert(newBookmarks, at: indexes)
-//                if item === bookmarkRoot || ov.isItemExpanded(item) {
-//                    if item !== bookmarkRoot {
-//                        indexes.shift(startingAt: 0, by: ov.row(forItem: item) + 1)
-//                    }
-//                    ov.selectRowIndexes(indexes, byExtendingSelection: false)
-//                }
-//                return true
-//            }
-//            return false
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, dragEndedWith operation: NSDragOperation) {
-//        draggedBookmarks = nil
-//    }
-//
-//    // MARK: - NSOutlineView delegate methods
-//
-//    func outlineView(_ ov: NSOutlineView, dataCellFor tableColumn: NSTableColumn?, item: Any) -> Any? {
-//        if tableColumn == nil {
-//            return (item as? SKBookmark)?.bookmarkType == .separator ? SKSeparatorCell() : nil
-//        }
-//        return tableColumn?.dataCell(forRow: ov.row(forItem: item))
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, item: Any) {
-//        guard let column = tableColumn else { return }
-//        
-//        if column.identifier == FILE_COLUMNID {
-//            if let bm = item as? SKBookmark {
-//                if bm.bookmarkType == .folder || bm.bookmarkType == .session {
-//                    (cell as? NSCell)?.textColor = .disabledControlTextColor
-//                } else {
-//                    (cell as? NSCell)?.textColor = .controlTextColor
-//                }
-//            }
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, shouldEditTableColumn tableColumn: NSTableColumn?, item: Any) -> Bool {
-//        guard let column = tableColumn, let tcID = column.identifier else { return false }
-//        guard let bm = item as? SKBookmark else { return false }
-//        
-//        switch tcID {
-//        case LABEL_COLUMNID:
-//            return bm.bookmarkType != .separator
-//        case PAGE_COLUMNID:
-//            return bm.pageIndex != NSNotFound
-//        default:
-//            return false
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, toolTipFor cell: NSCell, rect: UnsafeMutablePointer<NSRect>, tableColumn tc: NSTableColumn?, item: Any, mouseLocation: NSPoint) -> String {
-//        guard let column = tc, let tcID = column.identifier else { return "" }
-//        guard let bm = item as? SKBookmark else { return "" }
-//        
-//        switch tcID {
-//        case LABEL_COLUMNID:
-//            return bm.label
-//        case FILE_COLUMNID:
-//            if bm.bookmarkType == .session {
-//                return bm.children.map { $0.path ?? "" }.joined(separator: "\n")
-//            } else if bm.bookmarkType == .folder {
-//                let count = bm.countOfChildren
-//                return count == 1 ? NSLocalizedString("1 item", comment: "Bookmark folder description") : String.localizedStringWithFormat(NSLocalizedString("%ld items", comment: "Bookmark folder description"), count)
-//            } else {
-//                return bm.fileURL?.path ?? ""
-//            }
-//        case PAGE_COLUMNID:
-//            return bm.pageNumber?.stringValue ?? ""
-//        default:
-//            return ""
-//        }
-//    }
-//
-//    func outlineViewSelectionDidChange(_ notification: Notification) {
-//        updateStatus()
-//        if QLPreviewPanel.sharedPreviewPanelExists(), let previewPanel = QLPreviewPanel.shared() as? QLPreviewPanel, previewPanel.isVisible, previewPanel.dataSource === self {
-//            previewPanel.reloadData()
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, deleteItems items: [Any]) {
-//        endEditing()
-//        for item in minimumCoverForBookmarks(items as! [SKBookmark]).reversed() {
-//            guard let parent = item.parent, let itemIndex = parent.children.firstIndex(of: item) else { continue }
-//            parent.removeObjectFromChildren(at: itemIndex)
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, canDeleteItems items: [Any]) -> Bool {
-//        return !items.isEmpty
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, copyItems items: [Any]) {
-//        var urls = [URL]()
-//        addBookmarkURLsToArray(minimumCoverForBookmarks(items as! [SKBookmark]), urls)
-//        if !urls.isEmpty {
-//            let pboard = NSPasteboard.general
-//            pboard.clearContents()
-//            pboard.writeObjects(urls as [NSPasteboardWriting])
-//        } else {
-//            NSBeep()
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, canCopyItems items: [Any]) -> Bool {
-//        return !items.isEmpty
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, pasteFromPasteboard pboard: NSPasteboard) {
-//        guard let urls = NSURL.readFileURLs(from: pboard), !urls.isEmpty else { NSBeep(); return }
-//        
-//        let newBookmarks = SKBookmark.bookmarks(for: urls)
-//        if !newBookmarks.isEmpty {
-//            var item: SKBookmark?
-//            var anIndex = 0
-//            getInsertionFolder(&item, childIndex: &anIndex)
-//            let indexes = IndexSet(integersIn: anIndex..<(anIndex + newBookmarks.count))
-//            (item ?? bookmarkRoot).mutableArrayValue(forKey: "children").insert(newBookmarks, at: indexes)
-//            if item === bookmarkRoot || ov.isItemExpanded(item) {
-//                if item !== bookmarkRoot {
-//                    indexes.shift(startingAt: 0, by: ov.row(forItem: item) + 1)
-//                }
-//                ov.selectRowIndexes(indexes, byExtendingSelection: false)
-//            }
-//        } else {
-//            NSBeep()
-//        }
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, canPasteFromPasteboard pboard: NSPasteboard) -> Bool {
-//        return NSURL.canReadFileURL(from: pboard)
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, typeSelectHelperSelectionStrings typeSelectHelper: SKTypeSelectHelper) -> [String] {
-//        let count = ov.numberOfRows
-//        var labels = [String]()
-//        for i in 0..<count {
-//            if let label = ov.item(atRow: i) as? SKBookmark?.label {
-//                labels.append(label)
-//            }
-//        }
-//        return labels
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, typeSelectHelper typeSelectHelper: SKTypeSelectHelper, didFailToFindMatchForSearchString searchString: String) {
-//        statusBar.setLeftStringValue(String.localizedStringWithFormat(NSLocalizedString("No match: \"%@\"", comment: "Status message"), searchString))
-//    }
-//
-//    func outlineView(_ ov: NSOutlineView, typeSelectHelper typeSelectHelper: SKTypeSelectHelper, updateSearchString searchString: String?) {
-//        if let searchString = searchString {
-//            statusBar.setLeftStringValue(String.localizedStringWithFormat(NSLocalizedString("Finding: \"%@\"", comment: "Status message"), searchString))
-//        } else {
-//            updateStatus()
-//        }
-//    }
 //    
 //    // MARK: - Toolbar
 //
@@ -662,29 +374,31 @@ class KMBookmarkController: NSWindowController {
         
         var item = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(kBookmarksNewFolderToolbarItemIdentifier))
         item.label = NSLocalizedString("New Folder", comment: "Toolbar item label")
-//        item.setLabels(NSLocalizedString("New Folder", comment: "Toolbar item label"))
+        item.paletteLabel = NSLocalizedString("New Folder", comment: "Toolbar item label")
         item.toolTip = NSLocalizedString("Add a New Folder", comment: "Tool tip message")
-        item.image = NSImage(named: "NewFolder")
+//        item.image = NSImage(named: "NewFolder")
+        item.image = NSImage(named: NSImage.folderName)!
         item.target = self
-//        item.action = #selector(insertBookmarkFolder(_:))
+        item.action = #selector(insertBookmarkFolder(_:))
         dict[kBookmarksNewFolderToolbarItemIdentifier] = item
         
         item = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(kBookmarksNewSeparatorToolbarItemIdentifier))
         item.label = NSLocalizedString("New Separator", comment: "Toolbar item label")
-//        item.setLabels(NSLocalizedString("New Separator", comment: "Toolbar item label"))
+        item.paletteLabel = NSLocalizedString("New Separator", comment: "Toolbar item label")
         item.toolTip = NSLocalizedString("Add a New Separator", comment: "Tool tip message")
-        item.image = NSImage(named: "NewSeparator")
+//        item.image = NSImage(named: "NewSeparator")
+        item.image = NSImage(named: NSImage.shareTemplateName)!
         item.target = self
-//        item.action = #selector(insertBookmarkSeparator(_:))
+        item.action = #selector(insertBookmarkSeparator(_:))
         dict[kBookmarksNewSeparatorToolbarItemIdentifier] = item
         
         item = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(kBookmarksDeleteToolbarItemIdentifier))
         item.label = NSLocalizedString("Delete", comment: "Toolbar item label")
-//        item.setLabels(NSLocalizedString("Delete", comment: "Toolbar item label"))
+        item.paletteLabel = NSLocalizedString("Delete", comment: "Toolbar item label")
         item.toolTip = NSLocalizedString("Delete Selected Items", comment: "Tool tip message")
         item.image = NSWorkspace.shared.icon(forFileType: NSFileTypeForHFSTypeCode(OSType(kToolbarDeleteIcon)))
         item.target = self
-//        item.action = #selector(deleteBookmark(_:))
+        item.action = #selector(deleteBookmark(_:))
         dict[kBookmarksDeleteToolbarItemIdentifier] = item
         
         toolbarItems = dict
@@ -693,55 +407,6 @@ class KMBookmarkController: NSWindowController {
         self.window?.toolbar = toolbar
     }
 
-//    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdent: String, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
-//        return toolbarItems[itemIdent]
-//    }
-
-//    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
-//        return [
-//            kBookmarksNewFolderToolbarItemIdentifier,
-//            kBookmarksNewSeparatorToolbarItemIdentifier,
-//            kBookmarksDeleteToolbarItemIdentifier
-//        ]
-//    }
-//
-//    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
-//        return [
-//            kBookmarksNewFolderToolbarItemIdentifier,
-//            kBookmarksNewSeparatorToolbarItemIdentifier,
-//            kBookmarksDeleteToolbarItemIdentifier
-////            NSToolbarItem.Identifier.customizeToolbar
-////            NSToolbarFlexibleSpaceItemIdentifier,
-////            NSToolbarSpaceItemIdentifier,
-////            NSToolbarSeparatorItemIdentifier,
-////            NSToolbarCustomizeToolbarItemIdentifier
-//        ]
-//    }
-
-    func validateToolbarItem(_ toolbarItem: NSToolbarItem) -> Bool {
-//        guard let toolbar = self.window?.toolbar else { return false }
-//        
-//        if toolbar.customizationPaletteIsRunning {
-//            return false
-//        } else if toolbarItem.itemIdentifier == kBookmarksDeleteToolbarItemIdentifier {
-//            return outlineView.canDelete
-//        }
-        return true
-    }
-
-    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
-//        if menuItem.action == #selector(toggleStatusBar(_:)) {
-//            if statusBar.isVisible {
-//                menuItem.title = NSLocalizedString("Hide Status Bar", comment: "Menu item title")
-//            } else {
-//                menuItem.title = NSLocalizedString("Show Status Bar", comment: "Menu item title")
-//            }
-//            return true
-//        } else if menuItem.action == #selector(addBookmark(_:)) {
-//            return menuItem.tag == 0
-//        }
-        return true
-    }
 //
 //    // MARK: - Quick Look Panel Support
 //
@@ -818,7 +483,302 @@ class KMBookmarkController: NSWindowController {
 
 }
 
-extension KMBookmarkController: NSToolbarDelegate {
+extension KMBookmarkController: NSOutlineViewDelegate, NSOutlineViewDataSource {
+    //MARK: NSOutlineViewDataSource
+    
+        func minimumCoverForBookmarks(_ items: [KMBookmark]) -> [KMBookmark] {
+            var lastBm: KMBookmark?
+            var minimalCover = [KMBookmark]()
+    
+            for bm in items {
+                if lastBm != nil && !(bm.isDescendant(of: lastBm!)) {
+                    minimalCover.append(bm)
+                    lastBm = bm
+                }
+            }
+            return minimalCover
+        }
+    //
+    //    func outlineView(_ ov: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
+    //        let bookmark = item as? SKBookmark ?? bookmarkRoot
+    //        return bookmark.bookmarkType == .folder ? bookmark.countOfChildren : 0
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, isItemExpandable item: Any) -> Bool {
+    //        let bookmark = item as! SKBookmark
+    //        return bookmark.bookmarkType == .folder
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
+    //        let bookmark = (item as? SKBookmark) ?? bookmarkRoot
+    //        return bookmark.objectInChildren(at: index)!
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, objectValueFor tableColumn: NSTableColumn?, byItem item: Any?) -> Any? {
+    //        guard let column = tableColumn, let tcID = column.identifier else { return nil }
+    //        guard let bm = item as? SKBookmark else { return nil }
+    //
+    //        switch tcID {
+    //        case LABEL_COLUMNID:
+    //            return [SKTextWithIconStringKey: bm.label, SKTextWithIconImageKey: bm.icon]
+    //        case FILE_COLUMNID:
+    //            if bm.bookmarkType == .folder || bm.bookmarkType == .session {
+    //                let count = bm.countOfChildren
+    //                return count == 1 ? NSLocalizedString("1 item", comment: "Bookmark folder description") : String.localizedStringWithFormat(NSLocalizedString("%ld items", comment: "Bookmark folder description"), count)
+    //            } else {
+    //                return bm.fileURL?.path ?? ""
+    //            }
+    //        case PAGE_COLUMNID:
+    //            return bm.pageNumber
+    //        default:
+    //            return nil
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, setObjectValue object: Any?, for tableColumn: NSTableColumn?, byItem item: Any?) {
+    //        guard let column = tableColumn, let tcID = column.identifier else { return }
+    //        guard let bm = item as? SKBookmark else { return }
+    //
+    //        switch tcID {
+    //        case LABEL_COLUMNID:
+    //            if let newLabel = (object as? [String: Any])?[SKTextWithIconStringKey] as? String, newLabel != bm.label {
+    //                bm.label = newLabel
+    //            }
+    //        case PAGE_COLUMNID:
+    //            if let newPageNumber = object as? Int, newPageNumber != bm.pageNumber {
+    //                bm.pageNumber = newPageNumber
+    //            }
+    //        default:
+    //            break
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, writeItems items: [Any], to pboard: NSPasteboard) -> Bool {
+    //        draggedBookmarks = minimumCoverForBookmarks(items as! [SKBookmark])
+    //        pboard.clearContents()
+    //        pboard.setData(Data(), forType: SKPasteboardTypeBookmarkRows)
+    //        return true
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation {
+    //        guard index != NSOutlineViewDropOnItemIndex else { return .none }
+    //        guard let pboard = info.draggingPasteboard else { return .none }
+    //
+    //        if pboard.canReadItem(withDataConformingToTypes: [SKPasteboardTypeBookmarkRows]) && info.draggingSource as? NSOutlineView == ov {
+    //            return .move
+    //        } else if NSURL.canReadFileURL(from: pboard) {
+    //            return .every
+    //        }
+    //        return .none
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
+    //        guard let pboard = info.draggingPasteboard else { return false }
+    //
+    //        if pboard.canReadItem(withDataConformingToTypes: [SKPasteboardTypeBookmarkRows]) && info.draggingSource as? NSOutlineView == ov {
+    //            var movedBookmarks = [SKBookmark]()
+    //            var indexes = IndexSet()
+    //            var insertionIndex = index
+    //
+    //            let targetItem = item as? SKBookmark ?? bookmarkRoot
+    //
+    //            for bookmark in draggedBookmarks {
+    //                guard let parent = bookmark.parent else { continue }
+    //                guard let bookmarkIndex = parent.children.firstIndex(of: bookmark) else { continue }
+    //
+    //                if targetItem == parent {
+    //                    if insertionIndex > bookmarkIndex {
+    //                        insertionIndex -= 1
+    //                    }
+    //                    if insertionIndex == bookmarkIndex {
+    //                        continue
+    //                    }
+    //                }
+    //                parent.removeObjectFromChildren(at: bookmarkIndex)
+    //                targetItem.insertObject(bookmark, inChildrenAtIndex: insertionIndex)
+    //                movedBookmarks.append(bookmark)
+    //                insertionIndex += 1
+    //            }
+    //
+    //            for bookmark in movedBookmarks {
+    //                let row = ov.row(forItem: bookmark)
+    //                if row != -1 {
+    //                    indexes.insert(row)
+    //                }
+    //            }
+    //            if !indexes.isEmpty {
+    //                ov.selectRowIndexes(indexes, byExtendingSelection: false)
+    //            }
+    //            return true
+    //        } else {
+    //            guard let urls = NSURL.readFileURLs(from: pboard) else { return false }
+    //
+    //            let newBookmarks = SKBookmark.bookmarks(for: urls)
+    //            if !newBookmarks.isEmpty {
+    //                let indexes = IndexSet(integersIn: index..<(index + newBookmarks.count))
+    //                (item as? SKBookmark ?? bookmarkRoot).mutableArrayValue(forKey: "children").insert(newBookmarks, at: indexes)
+    //                if item === bookmarkRoot || ov.isItemExpanded(item) {
+    //                    if item !== bookmarkRoot {
+    //                        indexes.shift(startingAt: 0, by: ov.row(forItem: item) + 1)
+    //                    }
+    //                    ov.selectRowIndexes(indexes, byExtendingSelection: false)
+    //                }
+    //                return true
+    //            }
+    //            return false
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, dragEndedWith operation: NSDragOperation) {
+    //        draggedBookmarks = nil
+    //    }
+    
+    
+    //MARK: NSOutlineViewDelegate
+    //
+    //    func outlineView(_ ov: NSOutlineView, dataCellFor tableColumn: NSTableColumn?, item: Any) -> Any? {
+    //        if tableColumn == nil {
+    //            return (item as? SKBookmark)?.bookmarkType == .separator ? SKSeparatorCell() : nil
+    //        }
+    //        return tableColumn?.dataCell(forRow: ov.row(forItem: item))
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, willDisplayCell cell: Any, for tableColumn: NSTableColumn?, item: Any) {
+    //        guard let column = tableColumn else { return }
+    //
+    //        if column.identifier == FILE_COLUMNID {
+    //            if let bm = item as? SKBookmark {
+    //                if bm.bookmarkType == .folder || bm.bookmarkType == .session {
+    //                    (cell as? NSCell)?.textColor = .disabledControlTextColor
+    //                } else {
+    //                    (cell as? NSCell)?.textColor = .controlTextColor
+    //                }
+    //            }
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, shouldEditTableColumn tableColumn: NSTableColumn?, item: Any) -> Bool {
+    //        guard let column = tableColumn, let tcID = column.identifier else { return false }
+    //        guard let bm = item as? SKBookmark else { return false }
+    //
+    //        switch tcID {
+    //        case LABEL_COLUMNID:
+    //            return bm.bookmarkType != .separator
+    //        case PAGE_COLUMNID:
+    //            return bm.pageIndex != NSNotFound
+    //        default:
+    //            return false
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, toolTipFor cell: NSCell, rect: UnsafeMutablePointer<NSRect>, tableColumn tc: NSTableColumn?, item: Any, mouseLocation: NSPoint) -> String {
+    //        guard let column = tc, let tcID = column.identifier else { return "" }
+    //        guard let bm = item as? SKBookmark else { return "" }
+    //
+    //        switch tcID {
+    //        case LABEL_COLUMNID:
+    //            return bm.label
+    //        case FILE_COLUMNID:
+    //            if bm.bookmarkType == .session {
+    //                return bm.children.map { $0.path ?? "" }.joined(separator: "\n")
+    //            } else if bm.bookmarkType == .folder {
+    //                let count = bm.countOfChildren
+    //                return count == 1 ? NSLocalizedString("1 item", comment: "Bookmark folder description") : String.localizedStringWithFormat(NSLocalizedString("%ld items", comment: "Bookmark folder description"), count)
+    //            } else {
+    //                return bm.fileURL?.path ?? ""
+    //            }
+    //        case PAGE_COLUMNID:
+    //            return bm.pageNumber?.stringValue ?? ""
+    //        default:
+    //            return ""
+    //        }
+    //    }
+    //
+    //    func outlineViewSelectionDidChange(_ notification: Notification) {
+    //        updateStatus()
+    //        if QLPreviewPanel.sharedPreviewPanelExists(), let previewPanel = QLPreviewPanel.shared() as? QLPreviewPanel, previewPanel.isVisible, previewPanel.dataSource === self {
+    //            previewPanel.reloadData()
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, deleteItems items: [Any]) {
+    //        for item in minimumCoverForBookmarks(items as! [SKBookmark]).reversed() {
+    //            guard let parent = item.parent, let itemIndex = parent.children.firstIndex(of: item) else { continue }
+    //            parent.removeObjectFromChildren(at: itemIndex)
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, canDeleteItems items: [Any]) -> Bool {
+    //        return !items.isEmpty
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, copyItems items: [Any]) {
+    //        var urls = [URL]()
+    //        addBookmarkURLsToArray(minimumCoverForBookmarks(items as! [SKBookmark]), urls)
+    //        if !urls.isEmpty {
+    //            let pboard = NSPasteboard.general
+    //            pboard.clearContents()
+    //            pboard.writeObjects(urls as [NSPasteboardWriting])
+    //        } else {
+    //            NSBeep()
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, canCopyItems items: [Any]) -> Bool {
+    //        return !items.isEmpty
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, pasteFromPasteboard pboard: NSPasteboard) {
+    //        guard let urls = NSURL.readFileURLs(from: pboard), !urls.isEmpty else { NSBeep(); return }
+    //
+    //        let newBookmarks = SKBookmark.bookmarks(for: urls)
+    //        if !newBookmarks.isEmpty {
+    //            var item: SKBookmark?
+    //            var anIndex = 0
+    //            getInsertionFolder(&item, childIndex: &anIndex)
+    //            let indexes = IndexSet(integersIn: anIndex..<(anIndex + newBookmarks.count))
+    //            (item ?? bookmarkRoot).mutableArrayValue(forKey: "children").insert(newBookmarks, at: indexes)
+    //            if item === bookmarkRoot || ov.isItemExpanded(item) {
+    //                if item !== bookmarkRoot {
+    //                    indexes.shift(startingAt: 0, by: ov.row(forItem: item) + 1)
+    //                }
+    //                ov.selectRowIndexes(indexes, byExtendingSelection: false)
+    //            }
+    //        } else {
+    //            NSBeep()
+    //        }
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, canPasteFromPasteboard pboard: NSPasteboard) -> Bool {
+    //        return NSURL.canReadFileURL(from: pboard)
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, typeSelectHelperSelectionStrings typeSelectHelper: SKTypeSelectHelper) -> [String] {
+    //        let count = ov.numberOfRows
+    //        var labels = [String]()
+    //        for i in 0..<count {
+    //            if let label = ov.item(atRow: i) as? SKBookmark?.label {
+    //                labels.append(label)
+    //            }
+    //        }
+    //        return labels
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, typeSelectHelper typeSelectHelper: SKTypeSelectHelper, didFailToFindMatchForSearchString searchString: String) {
+    //        statusBar.setLeftStringValue(String.localizedStringWithFormat(NSLocalizedString("No match: \"%@\"", comment: "Status message"), searchString))
+    //    }
+    //
+    //    func outlineView(_ ov: NSOutlineView, typeSelectHelper typeSelectHelper: SKTypeSelectHelper, updateSearchString searchString: String?) {
+    //        if let searchString = searchString {
+    //            statusBar.setLeftStringValue(String.localizedStringWithFormat(NSLocalizedString("Finding: \"%@\"", comment: "Status message"), searchString))
+    //        } else {
+    //            updateStatus()
+    //        }
+    //    }
+    
+}
+
+extension KMBookmarkController: NSToolbarDelegate, NSToolbarItemValidation {
     func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
 //        return [.flexibleSpace, .yourItem1, .yourItem2, .yourItem3]
         return [
@@ -841,12 +801,32 @@ extension KMBookmarkController: NSToolbarDelegate {
     
     func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
         return toolbarItems[itemIdentifier.rawValue]
-//        let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
-//        toolbarItem.label = "Your Item Label"
-//        toolbarItem.paletteLabel = "Your Item Palette Label"
-//        toolbarItem.target = self
-//        toolbarItem.action = #selector(yourAction(_:))
-//        toolbarItem.image = NSImage(named: "YourItemImageName")
-//        return toolbarItem
+    }
+    
+    func validateToolbarItem(_ item: NSToolbarItem) -> Bool {
+//        guard let toolbar = self.window?.toolbar else { return false }
+//
+//        if toolbar.customizationPaletteIsRunning {
+//            return false
+//        } else if toolbarItem.itemIdentifier == kBookmarksDeleteToolbarItemIdentifier {
+//            return outlineView.canDelete
+//        }
+        return true
+    }
+}
+
+extension KMBookmarkController: NSMenuDelegate, NSMenuItemValidation {
+    func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
+//        if menuItem.action == #selector(toggleStatusBar(_:)) {
+//            if statusBar.isVisible {
+//                menuItem.title = NSLocalizedString("Hide Status Bar", comment: "Menu item title")
+//            } else {
+//                menuItem.title = NSLocalizedString("Show Status Bar", comment: "Menu item title")
+//            }
+//            return true
+//        } else if menuItem.action == #selector(addBookmark(_:)) {
+//            return menuItem.tag == 0
+//        }
+        return true
     }
 }

+ 37 - 0
PDF Office/PDF Master/Class/PDFTools/KMBookmark/Model/KMBookmark.swift

@@ -68,10 +68,47 @@ class KMBookmark: NSObject {
 //                return (id)[[SKFileBookmark alloc] initWithAliasData:[dictionary objectForKey:ALIASDATA_KEY] pageIndex:(pageIndex ? [pageIndex unsignedIntegerValue] : NSNotFound) label:[dictionary objectForKey:LABEL_KEY]];
 //            }
 //        }
+    
+    func insert(child: KMBookmark, atIndex: UInt) {
+        children.insert(child, at: Int(atIndex))
+        child.parent = self
+    }
+    
+    func isDescendant(of bookmark: KMBookmark) -> Bool {
+        if self == bookmark {
+            return true
+        }
+        for child in bookmark.children {
+            if self.isDescendant(of: child) {
+                return true
+            }
+        }
+        return false
+    }
+    
+    func isDescendant(ofArray bookmarks: [KMBookmark]) -> Bool {
+        for bm in bookmarks {
+            if self.isDescendant(of: bm) {
+                return true
+            }
+        }
+        return false
+    }
+    
+    func removeObjectFromChildren(index: Int) {
+        children[index].parent = nil
+        children.remove(at: index)
+    }
 }
 
 //MARK: Folder
 class KMFolderBookmark: KMBookmark {
+    static func folderBookmark(label: String) -> KMFolderBookmark {
+        let bookmark = KMFolderBookmark()
+        bookmark.label = label
+        return bookmark
+    }
+    
     override var bookmarkType: KMBookmarkType {
         get {
             return .folder