Browse Source

【综合】Bota大纲列表补充搜索

tangchao 1 year ago
parent
commit
ed3e9a98a1

+ 2 - 2
PDF Office/PDF Master.xcodeproj/xcuserdata/kdanmobile.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -462,8 +462,8 @@
             filePath = "PDF Master/Class/PDFWindowController/Side/LeftSide/Thumbnail/Base/KMPDFThumbViewBaseController.swift"
             startingColumnNumber = "9223372036854775807"
             endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "1113"
-            endingLineNumber = "1113"
+            startingLineNumber = "1116"
+            endingLineNumber = "1116"
             landmarkName = "menuItemAction_share(_:)"
             landmarkType = "7">
          </BreakpointContent>

+ 197 - 80
PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/KMLeftSideViewController.swift

@@ -299,6 +299,7 @@ class KMLeftSideViewController: KMSideViewController {
         self.noteOutlineView.indentationPerLevel = 0
 //        [noteOutlineView registerForDraggedTypes:[NSColor readableTypesForPasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]]];
         
+        self.outlineSearchField.delegate = self
         self.snapshotSearchField.backgroundColor = KMAppearance.Layout.l_1Color()
          self.outlineSearchField.backgroundColor = KMAppearance.Layout.l_1Color()
          self.noteSearchField.backgroundColor = KMAppearance.Layout.l_1Color()
@@ -1456,8 +1457,14 @@ class KMLeftSideViewController: KMSideViewController {
             }
             if (tag == 0) { // thumbnail Zoom In
                 scaling += 0.1
+                if scaling >= 2.2 {
+                    return
+                }
             } else if (tag == 1) { // thumbnail Zoom Out
                 scaling -= 0.1
+                if scaling <= 0.4 {
+                    return
+                }
             }
             sud.setValue(scaling, forKey: "KMThumbnailSizeScalingKey")
 
@@ -1605,6 +1612,20 @@ class KMLeftSideViewController: KMSideViewController {
             }
         }
     }
+    
+    func showSearchOutlineBlankState(_ toShowState: Bool) {
+        if (toShowState) {
+            self.leftSideEmptyVC.outlineSearchView.frame = CGRectMake((self.tocOutlineView.enclosingScrollView!.documentView!.frame.size.width - self.leftSideEmptyVC.outlineSearchView.bounds.size.width)/2.0, (self.tocOutlineView.enclosingScrollView!.documentView!.frame.size.height - self.leftSideEmptyVC.outlineSearchView.bounds.size.height)/2.0, self.leftSideEmptyVC.outlineSearchView.bounds.size.width, self.leftSideEmptyVC.outlineSearchView.bounds.size.height);
+            self.tocOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.outlineSearchView)
+            self.leftSideEmptyVC.outlineSearchView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
+        } else {
+            self.leftSideEmptyVC.outlineSearchView.removeFromSuperview()
+        }
+    }
+    
+//    func allRangeOfRoughString(_ roughString: String, searchString: String) -> [NSRange] {
+//
+//    }
 }
 
 // MARK: - KMBotaTableViewDelegate
@@ -1992,19 +2013,25 @@ extension KMLeftSideViewController {
     }
     
     private func _hasContainString(_ searchString: String, rootOutline outline: CPDFOutline) -> Bool {
+        let label_low = outline.label.lowercased()
+        let searchString_low = searchString.lowercased()
+        if label_low.contains(searchString_low) {
 //        if ([outline.label rangeOfString:searchString options:self.outlineIgnoreCaseFlag?NSCaseInsensitiveSearch:0].location != NSNotFound){
-//            return YES;
-//        } else {
-//            BOOL subHas = NO;
-//            for (NSUInteger i = 0; i < outline.numberOfChildren; i ++) {
-//                PDFOutline *subOutline = [outline childAtIndex:i];
-//                subHas = [self hasContainString:searchString rootOutline:subOutline];
-//                if (subHas) {
-//                    break;
-//                }
-//            }
-//            return subHas;
-//        }
+            return true
+        } else {
+            var subHas = false
+            for i in 0 ..< outline.numberOfChildren {
+                if let subOutline = outline.child(at: i) {
+                    subHas = self._hasContainString(searchString, rootOutline: subOutline)
+                } else {
+                    continue
+                }
+                if (subHas) {
+                    break
+                }
+            }
+            return subHas
+        }
         return false
     }
 }
@@ -2971,74 +2998,96 @@ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSour
     func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int {
         if outlineView.isEqual(to: self.tocOutlineView) {
             let isLocked = self.listView.document?.isLocked ?? true
-            if item == nil && isLocked == false {
-                var item = self.listView.document.outlineRoot()
-                if let data = item?.numberOfChildren, data == 0 && !self.isSearchOutlineMode {
-                    let view = self.tocOutlineView.enclosingScrollView!
-                    let emptyVcSize =  self.leftSideEmptyVC.emptyOutlineView.frame.size
-//
-                    self.leftSideEmptyVC.emptyOutlineView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height)
-                    
-                    self.leftSideEmptyVC.emptyOutlineView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
-                    self.tocOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptyOutlineView)
-                    self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = false
+            if isLocked { // 文档不存在 或 已加锁
+                return 0
+            }
+            if item == nil { // 第一层
+                // 获取根
+                guard let outline = self.listView.document.outlineRoot() else {
+                    return 0
+                }
+                if outline.numberOfChildren == 0 {
+                    return 0
+                }
+                
+                if self.isSearchOutlineMode { // 是否为搜索模块
+                    if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: outline) {
+                        self.showSearchOutlineBlankState(false)
+                    } else {
+                        self.showSearchOutlineBlankState(true)
+                        return 0
+                    }
                 } else {
-                    self.leftSideEmptyVC.emptyOutlineView.removeFromSuperview()
-                    self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = true
+                    if outline.numberOfChildren > 0 { // 有数据
+                        self.leftSideEmptyVC.emptyOutlineView.removeFromSuperview()
+                        self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = true
+                    } else { // 没有数据
+                        let view = self.tocOutlineView.enclosingScrollView!
+                        let emptyVcSize =  self.leftSideEmptyVC.emptyOutlineView.frame.size
+    //
+                        self.leftSideEmptyVC.emptyOutlineView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height)
+                        self.leftSideEmptyVC.emptyOutlineView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
+                        self.tocOutlineView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptyOutlineView)
+                        self.leftSideEmptyVC.deleteOutlineBtn.isEnabled = false
+                        return 0
+                    }
                 }
-                if let data = item?.numberOfChildren, data > 0 {
+
+                // 搜索按钮
+                if outline.numberOfChildren > 0 {
                     self.outlineSearchButton.isEnabled = true
                 } else {
                     self.outlineSearchButton.isEnabled = false
                 }
                 
                 if (self.isSearchOutlineMode) {
-                    if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: item!) {
-//                        [self showSearchOutlineBlankState:NO];
-                    } else {
-//                        [self showSearchOutlineBlankState:YES];
+                    var num = 0
+                    for i in 0 ..< outline.numberOfChildren {
+                        if let child = outline.child(at: i) {
+                            if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: child) {
+                                num += 1
+                            }
+                        }
                     }
+                    return num
+                } else {
+                    let array = self.listView.document.bookmarks() ?? [CPDFBookmark]()
+                    var bookmarkNum = 0
+                    if array.isEmpty == false {
+                        bookmarkNum = 1
+                    }
+                    return Int(outline.numberOfChildren) + bookmarkNum
                 }
-                
-                let array = self.listView.document.bookmarks() ?? [CPDFBookmark]()
-//                var bookMarks: [KMBookMarkItem] = []
-//                for bookMark in array {
-//                    let item = KMBookMarkItem()
-//                    item.bookMark = bookMark
-//                    item.index = UInt(bookMark.pageIndex)
-//                    item.label = bookMark.label
-//                    bookMarks.append(item)
-//                }
-                var bookmarkNum = 0
-                if array.isEmpty == false {
-                    bookmarkNum = 1
+            } else { // 第二层 +
+                if self.isSearchOutlineMode {
+                    if let data = item as? String, data == "Bookmarks" { // 书签group
+                        return 0
+                    } else if item is CPDFOutline { // 大纲
+                        let child = item as! CPDFOutline
+                        if child.numberOfChildren == 0 {
+                            return 0
+                        }
+                        var num = 0
+                        for i in 0 ..< child.numberOfChildren {
+                            if let _child = child.child(at: i) {
+                                if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: _child) {
+                                    num += 1
+                                }
+                            }
+                        }
+                        return num
+                    } else if item is CPDFBookmark { // 书签
+                        return 0
+                    }
+                } else {
+                    if let data = item as? String, data == "Bookmarks" { // 书签group
+                        return (self.listView.document?.bookmarks().count) ?? 0
+                    } else if item is CPDFOutline { // 大纲
+                        return Int((item as? CPDFOutline)?.numberOfChildren ?? 0)
+                    } else if item is CPDFBookmark { // 书签
+                        return 0
+                    }
                 }
-                return Int(item?.numberOfChildren ?? 0) + bookmarkNum
-            }
-            if (self.isSearchOutlineMode) {
-//                var num = 0
-//                for (NSUInteger i = 0; i < [(PDFOutline *)item numberOfChildren]; i++) {
-//                    PDFOutline *outline = [(PDFOutline *)item childAtIndex:i];
-//                    if ([self hasContainString:self.leftSideController.outlineSearchField.stringValue rootOutline:outline]) {
-//                        num ++;
-//                    }
-//                }
-//                return num;
-            } else {
-//                return [(PDFOutline *)item numberOfChildren];
-            }
-//            if item is CPDFBookmark {
-//                return 0
-//            }
-//            return Int((item as? CPDFOutline)?.numberOfChildren ?? 0)
-            let array = self.listView.document?.bookmarks() ?? [CPDFBookmark]()
-            if let data = item as? String, data == "Bookmarks" {
-                return array.count
-            } else if item is CPDFOutline {
-//                return Int(item?.numberOfChildren ?? 0)
-                return Int((item as? CPDFOutline)?.numberOfChildren ?? 0)
-            } else if item is CPDFBookmark {
-                return 0
             }
         } else if outlineView.isEqual(to: self.noteOutlineView) {
             var count = 0
@@ -3094,21 +3143,46 @@ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSour
     
     func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any {
         if outlineView.isEqual(to: self.tocOutlineView) {
+            let isLocked = self.listView.document?.isLocked ?? true
+            if isLocked { // 文档不存在 或 已加锁
+                return ""
+            }
+            
             let array = self.listView.document.bookmarks() ?? [CPDFBookmark]()
             var bookmarkNum = 0
             if array.isEmpty == false {
                 bookmarkNum = 1
             }
-            
-            if item == nil && self.listView.document.isLocked == false {
-                if index == 0 && bookmarkNum == 1 {
-                    return "Bookmarks"
+            if item == nil {
+                if self.isSearchOutlineMode {
+                    guard let outline = self.listView.document.outlineRoot() else {
+                        return ""
+                    }
+                    if outline.numberOfChildren == 0 {
+                        return ""
+                    }
+                    var array: [CPDFOutline] = []
+                    for i in 0 ..< outline.numberOfChildren {
+                        if let child = outline.child(at: i) {
+                            if self._hasContainString(self.outlineSearchField.stringValue, rootOutline: child) {
+                                array.append(child)
+                            }
+                        }
+                    }
+                    
+                    if index < array.count {
+                        return array[index]
+                    }
+                    return ""
                 } else {
-                    var _index = bookmarkNum == 1 ? index-1 : index
-                    var _item: CPDFOutline?
-                    _item = self.listView.document.outlineRoot()
-                    var obj = _item?.child(at: UInt(_index))
-                    return obj as Any
+                    if index == 0 && bookmarkNum == 1 {
+                        return "Bookmarks"
+                    } else {
+                        var _index = bookmarkNum == 1 ? index-1 : index
+                        let outline = self.listView.document.outlineRoot()
+                        var obj = outline?.child(at: UInt(_index))
+                        return obj as Any
+                    }
                 }
             } else {
                 if let data = item as? String, data == "Bookmarks" {
@@ -3116,9 +3190,10 @@ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSour
                 } else if item is CPDFOutline {
                     return (item as! CPDFOutline).child(at: UInt(index))
                 } else if item is CPDFBookmark {
-//                    return nil?
+                    return ""
                 }
             }
+            
 //            var obj = _item?.child(at: UInt(index))
 //            if (self.isSearchOutlineMode) {
 //                NSMutableArray *array = [NSMutableArray array];
@@ -3253,6 +3328,7 @@ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSour
             if tcID == LABEL_COLUMNID {
                 if (self.isSearchOutlineMode) {
 //                    NSString *roughString = [[ol label] stringByCollapsingWhitespaceAndNewlinesAndRemovingSurroundingWhitespaceAndNewlines];
+                    let roughString = title
 //                    NSArray *arr = [self allRangeOfRoughString:roughString searchString:self.leftSideController.outlineSearchField.stringValue];
 //                    NSMutableAttributedString *attributeString = [[[NSMutableAttributedString alloc] initWithString:roughString] autorelease];
 //
@@ -3263,6 +3339,7 @@ extension KMLeftSideViewController: NSOutlineViewDelegate, NSOutlineViewDataSour
 //                        [attributeString addAttribute:NSFontAttributeName value:[NSFont boldSystemFontOfSize:13] range:range];
 //                    }
 //                    cell.tocLabel.attributedStringValue = attributeString;
+                    cell.tocLabel.stringValue = title
                 } else {
                     cell.tocLabel.stringValue = title
                 }
@@ -4144,7 +4221,47 @@ extension KMLeftSideViewController: KMNoteOutlineViewDelegate {
 }
 
 extension KMLeftSideViewController: NSSearchFieldDelegate {
-    
+    func controlTextDidChange(_ obj: Notification) {
+        if self.outlineSearchField.isEqual(to: obj.object) {
+            if (self.outlineSearchField.stringValue.isEmpty == false) {
+                self.isSearchOutlineMode = true
+                
+                self.tocOutlineView.reloadData()
+                self.tocOutlineView.expandItem(nil, expandChildren: true)
+                self.tocType = .unfold
+            } else {
+                self.isSearchOutlineMode = false
+                self.showSearchOutlineBlankState(false)
+                self.tocOutlineView.reloadData()
+            }
+    //        self.leftSideEmptyVC.addOutlineBtn.enabled = !self.isSearchOutlineMode;
+            self.outlineAddButton.isEnabled = !self.isSearchOutlineMode
+        }
+//        else if ([obj.object isEqual:self.leftSideController.snapshotSearchField]) {
+//            NSString *searchString = [self.leftSideController.snapshotSearchField stringValue];
+//            NSPredicate *filterPredicate = nil;
+//            if ([searchString length] > 0) {
+//                NSExpression *lhs = [NSExpression expressionForConstantValue:searchString];
+//                NSExpression *rhs = [NSExpression expressionForKeyPath:@"string"];
+//                NSUInteger options = NSDiacriticInsensitivePredicateOption;
+//                if (mwcFlags.caseInsensitiveNoteSearch)
+//                    options |= NSCaseInsensitivePredicateOption;
+//                filterPredicate = [NSComparisonPredicate predicateWithLeftExpression:lhs rightExpression:rhs modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:options];
+//            }
+//            [rightSideController.snapshotArrayController setFilterPredicate:filterPredicate];
+//
+//            NSArray * snapshots = [rightSideController.snapshotArrayController arrangedObjects];
+//            if (snapshots.count > 0) {
+//                [self.leftSideEmptyVC.outlineSearchView removeFromSuperview];
+//            } else {
+//                NSView *view = rightSideController.snapshotTableView.enclosingScrollView;
+//                CGSize emptyVcSize =  self.leftSideEmptyVC.outlineSearchView.frame.size;
+//                self.leftSideEmptyVC.outlineSearchView.frame = NSMakeRect((view.frame.size.width-emptyVcSize.width)/2.0,(view.frame.size.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height);
+//                self.leftSideEmptyVC.outlineSearchView.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin| NSViewMaxYMargin | NSViewMinYMargin;
+//                [rightSideController.snapshotTableView.enclosingScrollView.documentView addSubview:self.leftSideEmptyVC.outlineSearchView];
+//            }
+//        }
+    }
 }
 
 extension KMLeftSideViewController: NSMenuDelegate {

File diff suppressed because it is too large
+ 8 - 8
PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/LeftSideView.xib


+ 3 - 0
PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/Thumbnail/Base/KMPDFThumbViewBaseController.swift

@@ -184,6 +184,9 @@ class KMPDFThumbViewBaseController: KMBaseViewController {
         let panel = NSOpenPanel()
         panel.allowedFileTypes = ["pdf"]
         panel.beginSheetModal(for: self.view.window!) { response in
+            if response == .cancel {
+                return
+            }
             let windowC = KMPDFEditInsertPageWindow(document: self.thumbnailView.document!, path: panel.urls.first!, password: self.thumbnailView.document?.password)
             windowC.callback = { [weak self] pdfDoc, pwd, pages, insertIdx in
                 var indexs = IndexSet()