瀏覽代碼

【2025】【BOTA】大纲列表ui处理

tangchao 3 月之前
父節點
當前提交
8eb2f09ac7

+ 21 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Outline/KMImageNameBotaClose.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "icon_prefix.pdf",
+      "idiom" : "universal"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 83 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Outline/KMImageNameBotaClose.imageset/icon_prefix.pdf

@@ -0,0 +1,83 @@
+%PDF-1.7
+
+1 0 obj
+  << >>
+endobj
+
+2 0 obj
+  << /Length 3 0 R >>
+stream
+/DeviceRGB CS
+/DeviceRGB cs
+q
+1.000000 0.000000 -0.000000 1.000000 3.333344 3.203125 cm
+0.533333 0.549020 0.580392 scn
+0.195262 9.267629 m
+0.455612 9.527978 0.877722 9.527978 1.138071 9.267629 c
+4.666667 5.739033 l
+8.195263 9.267629 l
+8.455612 9.527978 8.877722 9.527978 9.138071 9.267629 c
+9.398421 9.007279 9.398421 8.585169 9.138071 8.324820 c
+5.609476 4.796224 l
+9.138071 1.267628 l
+9.398421 1.007278 9.398421 0.585169 9.138071 0.324820 c
+8.877722 0.064469 8.455612 0.064469 8.195263 0.324820 c
+4.666667 3.853415 l
+1.138071 0.324820 l
+0.877722 0.064469 0.455612 0.064469 0.195262 0.324820 c
+-0.065087 0.585169 -0.065087 1.007278 0.195262 1.267628 c
+3.723858 4.796224 l
+0.195262 8.324820 l
+-0.065087 8.585169 -0.065087 9.007279 0.195262 9.267629 c
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  760
+endobj
+
+4 0 obj
+  << /Annots []
+     /Type /Page
+     /MediaBox [ 0.000000 0.000000 16.000000 16.000000 ]
+     /Resources 1 0 R
+     /Contents 2 0 R
+     /Parent 5 0 R
+  >>
+endobj
+
+5 0 obj
+  << /Kids [ 4 0 R ]
+     /Count 1
+     /Type /Pages
+  >>
+endobj
+
+6 0 obj
+  << /Pages 5 0 R
+     /Type /Catalog
+  >>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000010 00000 n
+0000000034 00000 n
+0000000850 00000 n
+0000000872 00000 n
+0000001045 00000 n
+0000001119 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+1178
+%%EOF

+ 21 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Outline/KMImageNameBotaSearch.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "button.pdf",
+      "idiom" : "universal"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 60 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Outline/KMImageNameBotaSearch.imageset/button.pdf

@@ -0,0 +1,60 @@
+%PDF-1.7
+
+1 0 obj
+  << >>
+endobj
+
+2 0 obj
+  << /Filter /FlateDecode
+     /Length 3 0 R
+  >>
+stream
+xe’Án1„ïyŠ=#‘Ú‰íØW@â<ª¤þ•P%ž¿“í¿ÎVÍ)ûÅñŒgóðíñÿßýñç÷/Û×_åa}í/å_áJÇÚèÜ|ÎÝÇ3®b>”¶ýV¨6¥ðyÚ†(ÏMo*AÛËþ\´*nàŽTêŒÒíVFÜc±8«´zk̼ˆŸ5{IÆÐê[¶âvÖ¥âB{éµ¹ñrÖe·DÑdi-{¥ý”L²—?kôVõ�ÞŠÕ!Þµ/6ªGè˜U!ƒ% !��É1tƒm±0¤‹–Ñh{*ÜÑ„zÇ•ŒÕ0ª;�ÀË€K20L¨.L§ÖÙð·WŽµÁ’7�qA×ñÎ�¹³áXûP³í0pæ¬íeznÒå÷X—n‰.ªÉ¤FtsA:÷^\J&™¡Ï ”¡i�f3êÛ
+¯ýDð³�P´’¸¨¬ÊÆy�»±Œ	¥6:`ɇq$Ò˜o°£Q'vXŠ7K@wåDÈqo	·îã]·‡¿TÅU<ÇÓôÂÊÇ™ŸÅïOå¹ü(¯álÆ
+endstream
+endobj
+
+3 0 obj
+  408
+endobj
+
+4 0 obj
+  << /Annots []
+     /Type /Page
+     /MediaBox [ 0.000000 0.000000 16.000000 16.000000 ]
+     /Resources 1 0 R
+     /Contents 2 0 R
+     /Parent 5 0 R
+  >>
+endobj
+
+5 0 obj
+  << /Kids [ 4 0 R ]
+     /Count 1
+     /Type /Pages
+  >>
+endobj
+
+6 0 obj
+  << /Pages 5 0 R
+     /Type /Catalog
+  >>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000010 00000 n
+0000000034 00000 n
+0000000526 00000 n
+0000000548 00000 n
+0000000721 00000 n
+0000000795 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+854
+%%EOF

+ 367 - 136
PDF Office/PDF Master/KMClass/Left/Outline/Controller/KMOutlineViewController.swift

@@ -42,13 +42,18 @@ class KMOutlineViewController: KMNBaseViewController {
     
     private lazy var addButton_: ComponentButton = {
         let view = ComponentButton()
-        view.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, state: .normal, isDisable: false, onlyIcon: true)
+        view.properties = ComponentButtonProperty(type: .text_gray, size: .xxs, state: .normal, isDisable: false, onlyIcon: true, keepPressState: false)
         return view
     }()
     
     private lazy var moreDropdown_: ComponentDropdown = {
         let view = ComponentDropdown()
-        view.properties = ComponentDropdownProperty(type: .default_Icon, size: .xxs, state: .normal, split: false, disabled: false)
+        view.properties = ComponentDropdownProperty(type: .split_primary, size: .xxs, state: .normal, split: false, disabled: false)
+        return view
+    }()
+    
+    private lazy var headerSearchView_: KMNBotaHeaderSearchView? = {
+        let view = KMNBotaHeaderSearchView.createFromNib()
         return view
     }()
     
@@ -85,6 +90,7 @@ class KMOutlineViewController: KMNBaseViewController {
         searchButton_.km_add_size_constraint(size: NSMakeSize(24, 24))
         searchButton_.km_add_centerY_constraint(constant: 1)
         searchButton_.km_add_trailing_constraint(equalTo: addButton, attribute: .leading, constant: -4)
+        searchButton_.setTarget(self, action: #selector(_searchAction))
         
         addButton.addSubview(addButton_)
         addButton_.km_add_size_constraint(size: NSMakeSize(24, 24))
@@ -99,6 +105,20 @@ class KMOutlineViewController: KMNBaseViewController {
         moreDropdown_.km_add_centerY_constraint()
         moreDropdown_.componentDelegate = self
         
+        if let data = headerSearchView_ {
+            topView.addSubview(data)
+            headerSearchView_?.frame = topView.bounds
+            headerSearchView_?.autoresizingMask = [.width, .height]
+        }
+        _hideHeaderSearch()
+        headerSearchView_?.itemClick = { [weak self] idx, _ in
+            if idx == 1 { // 忽略大小写
+                
+            } else if idx == 2 { // 关闭搜索
+                self?._hideHeaderSearch()
+            }
+        }
+        
         emptyView.wantsLayer = true
         bigTipLabel.stringValue = ""
         tipLabel.stringValue = ""
@@ -109,7 +129,6 @@ class KMOutlineViewController: KMNBaseViewController {
         emptyView_.km_add_leading_constraint()
         emptyView_.km_add_trailing_constraint()
         
-
         self.BOTAOutlineView.delegate = self
         self.BOTAOutlineView.inputData = self.handdler.outlineRoot()
         self.BOTAOutlineView.outlineView.doubleAction = #selector(outlineViewDoubleAction)
@@ -132,10 +151,14 @@ class KMOutlineViewController: KMNBaseViewController {
         
         KMMainThreadExecute {
             self.contendView.wantsLayer = true
-            let color = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle")
+            let color = KMNColorTools.colorBg_layoutMiddle()
             self.contendView.layer?.backgroundColor = color.cgColor
+            self.headerSearchView_?.wantsLayer = true
+            self.headerSearchView_?.layer?.backgroundColor = color.cgColor
+            self.headerSearchView_?.bottomLine.wantsLayer = true
+            self.headerSearchView_?.bottomLine.layer?.backgroundColor = KMNColorTools.colorPrimary_border1().cgColor
             
-            self.titleLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
+            self.titleLabel.textColor = KMNColorTools.colorText_2()
             
             self.addButton_.properties.icon = NSImage(named: "KMBookmarkAdd")
             self.addButton_.reloadData()
@@ -143,7 +166,7 @@ class KMOutlineViewController: KMNBaseViewController {
             self.searchButton_.properties.icon = NSImage(named: "KMImageNameOutlineSearch")
             self.searchButton_.reloadData()
             
-            let dividerColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/divider")
+            let dividerColor = KMNColorTools.colorBorder_divider()
             self.topSepline.wantsLayer = true
             self.topSepline.layer?.backgroundColor = dividerColor.cgColor
             self.lineView.backgroundColor(dividerColor)
@@ -196,7 +219,7 @@ class KMOutlineViewController: KMNBaseViewController {
         let point = event.locationInWindow
         let tempView = view
         var viewHeight: CGFloat = 0
-        let items: [String] = ["Add Item", "Add Sub-Item", "Add A Higher Level","", "Delete","", "Edit", "Rename", "Change Destination","", "Promote", "Promote"]
+        let items: [String] = ["Add Item", "Add Sub-Item", "Add A Higher Level","", "Delete","", "Edit", "Rename", "Change Destination","", "Promote", "Demote"]
         var menuItemArr: [ComponentMenuitemProperty] = []
         for value in items {
             if value.count == 0 {
@@ -215,10 +238,113 @@ class KMOutlineViewController: KMNBaseViewController {
                 viewHeight += 36
             }
         }
-//        if idxs > 1 {
-//            (menuItemArr.safe_element(for: 1) as? ComponentMenuitemProperty)?.isDisabled = true
-//            (menuItemArr.safe_element(for: 2) as? ComponentMenuitemProperty)?.isDisabled = true
-//        }
+
+        if self.BOTAOutlineView.outlineView.selectedRowIndexes.count > 1 {
+//            if action == #selector(deleteItemAction) {
+//                return true
+//            }
+//            return false
+            for data in menuItemArr {
+                if data.text == KMLocalizedString("Delete") {
+                    data.isDisabled = false
+                } else {
+                    data.isDisabled = true
+                }
+            }
+            if menuGroupView_ == nil {
+                menuGroupView_ = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
+            }
+            
+            if menuGroupView_ != nil {
+                menuGroupView_?.clickedAutoHide = false
+                menuGroupView_?.groupDelegate = self
+                menuGroupView_?.frame = CGRectMake(0, 0, 180, viewHeight)
+                menuGroupView_?.updateGroupInfo(menuItemArr)
+                
+                menuGroupView_?.showWithPoint(CGPoint(x: point.x, y: point.y - viewHeight), relativeTo: tempView)
+            }
+            return
+        } else if self.BOTAOutlineView.outlineView.selectedRowIndexes.count > 0 {
+//            if action == #selector(addChildItemAction) || action == #selector(changeItemAction) {
+//                return true
+//            }
+            for data in menuItemArr {
+                if data.text == KMLocalizedString("Add Sub-Item") || data.text == KMLocalizedString("Change Destination") {
+                    data.isDisabled = false
+                } else {
+//                    data.isDisabled = true
+                }
+            }
+        }
+        if self.BOTAOutlineView.outlineView.clickedRow == -1 {
+//            if action == #selector(addItemAction) {
+//                return true
+//            } else {
+//                return false
+//            }
+            for data in menuItemArr {
+                if data.text == KMLocalizedString("Add Item") {
+                    data.isDisabled = false
+                } else {
+                    data.isDisabled = true
+                }
+            }
+        } else {
+            let outlineItem : KMBOTAOutlineItem = self.BOTAOutlineView.outlineView.item(atRow: self.BOTAOutlineView.outlineView.clickedRow) as! KMBOTAOutlineItem
+            if outlineItem.outline.index > 0 {
+//                if action == #selector(demoteItemAction) {
+//                    return true
+//                }
+                for data in menuItemArr {
+                    if data.text == KMLocalizedString("Demote") {
+                        data.isDisabled = false
+                    } else {
+//                        data.isDisabled = true
+                    }
+                }
+            } else {
+//                if action == #selector(demoteItemAction) {
+//                    return false
+//                }
+                for data in menuItemArr {
+                    if data.text == KMLocalizedString("Demote") {
+                        data.isDisabled = true
+                    } else {
+//                        data.isDisabled = true
+                    }
+                }
+            }
+            
+            let parentOutline = outlineItem.outline.parent
+            let grandparentOutline = parentOutline?.parent
+            if grandparentOutline != nil {
+//                if action == #selector(addHigherItemAction) {
+//                    return true
+//                } else if action == #selector(promoteItemAction) {
+//                    return true
+//                }
+                for data in menuItemArr {
+                    if data.text == KMLocalizedString("Add A Higher Level") || data.text == KMLocalizedString("Promote") {
+                        data.isDisabled = false
+                    } else {
+//                        data.isDisabled = true
+                    }
+                }
+            } else {
+//                if action == #selector(addHigherItemAction) {
+//                    return false
+//                } else if action == #selector(promoteItemAction) {
+//                    return false
+//                }
+                for data in menuItemArr {
+                    if data.text == KMLocalizedString("Add A Higher Level") || data.text == KMLocalizedString("Promote") {
+                        data.isDisabled = true
+                    } else {
+//                        data.isDisabled = true
+                    }
+                }
+            }
+        }
         
         if menuGroupView_ == nil {
             menuGroupView_ = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
@@ -296,6 +422,14 @@ class KMOutlineViewController: KMNBaseViewController {
         return alert.runModal()
     }
     
+    private func _showHeaderSearch() {
+        headerSearchView_?.isHidden = false
+    }
+    
+    private func _hideHeaderSearch() {
+        headerSearchView_?.isHidden = true
+    }
+    
     //MARK: - GroupView
     
     func showGroupView() {
@@ -311,6 +445,43 @@ class KMOutlineViewController: KMNBaseViewController {
             viewHeight += 36
         }
         
+        if let data =  menuItemArr.first {
+            var canExpand = false
+            for row in 0..<self.BOTAOutlineView.outlineView.numberOfRows {
+                // 检查当前项目是否可以展开
+                let item = self.BOTAOutlineView.outlineView.item(atRow: row)
+                if self.BOTAOutlineView.outlineView.isExpandable(item) {
+                    if !self.BOTAOutlineView.outlineView.isItemExpanded(item) {
+                        canExpand = true
+                        break
+                    }
+                }
+            }
+            data.isDisabled = !canExpand
+        }
+        
+        if let data = menuItemArr.safe_element(for: 1) as? ComponentMenuitemProperty {
+            var canCollapse = false
+            for row in 0..<self.BOTAOutlineView.outlineView.numberOfRows {
+                let item = self.BOTAOutlineView.outlineView.item(atRow: row)
+                if self.BOTAOutlineView.outlineView.isExpandable(item) {
+                    if self.BOTAOutlineView.outlineView.isItemExpanded(item) {
+                        canCollapse = true
+                        break
+                    }
+                }
+            }
+            data.isDisabled = !canCollapse
+        }
+        
+        if let data = menuItemArr.last {
+            if self.BOTAOutlineView.outlineView.item(atRow: 0) != nil {
+                data.isDisabled = false
+            } else {
+                data.isDisabled = true
+            }
+        }
+        
         if groupView_ == nil {
             groupView_ = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
         }
@@ -333,11 +504,7 @@ class KMOutlineViewController: KMNBaseViewController {
         moreDropdown_.properties.state = .normal
         moreDropdown_.reloadData()
     }
-}
-
-
-//Data
-extension KMOutlineViewController {
+    
     func updateExtempViewState() {
         if(self.handdler.outlineRoot() == nil || self.handdler.outlineRoot()?.numberOfChildren == 0) { //无数据时的图
             self.emptyView.isHidden = false
@@ -347,7 +514,9 @@ extension KMOutlineViewController {
     }
 }
 
+
 //MARK: -  Notification
+
 extension KMOutlineViewController {
     @objc func KMPDFViewCurrentPageDidChangedNotification(notification: NSNotification) {
         if notification.object is CPDFDocument {
@@ -371,16 +540,18 @@ extension KMOutlineViewController {
     }
     
     @objc func addItemAction() {
-        let outlineView: KMOutlineView = self.BOTAOutlineView.outlineView
+        guard let outlineView = BOTAOutlineView.outlineView else {
+            return
+        }
         let selectRowIndexs = outlineView.selectedRowIndexes
-        let dataCount = self.BOTAOutlineView.data?.children.count
-        var index: Int
-        var parent: KMBOTAOutlineItem = KMBOTAOutlineItem()
-        var outlineItem: KMBOTAOutlineItem = KMBOTAOutlineItem()
+        let dataCount = BOTAOutlineView.data?.children.count ?? 0
+        var index: Int = 0
+        var parent: KMBOTAOutlineItem?
+        var outlineItem: KMBOTAOutlineItem?
 
         if selectRowIndexs.count == 0 {
-            var lastOulineItem = KMBOTAOutlineItem()
-            if dataCount == nil || dataCount == 0 {
+            var lastOulineItem: KMBOTAOutlineItem?
+            if dataCount == 0 {
                 let item = KMBOTAOutlineItem()
                 item.outline = self.handdler.document!.setNewOutlineRoot()
                 item.parent = nil
@@ -388,18 +559,18 @@ extension KMOutlineViewController {
                 
                 lastOulineItem = item
             } else {
-                outlineItem = outlineView.item(atRow: outlineView.numberOfRows - 1) as! KMBOTAOutlineItem
+                outlineItem = outlineView.item(atRow: outlineView.numberOfRows - 1) as? KMBOTAOutlineItem
                 lastOulineItem = outlineItem
-                while lastOulineItem.parent != nil {
-                    lastOulineItem = lastOulineItem.parent!
+                while lastOulineItem?.parent != nil {
+                    lastOulineItem = lastOulineItem?.parent
                 }
                 parent = lastOulineItem
             }
-            index = Int(lastOulineItem.outline.numberOfChildren)
+            index = Int(lastOulineItem?.outline.numberOfChildren ?? 0)
         } else {
-            outlineItem = outlineView.item(atRow: selectRowIndexs.last ?? 0) as! KMBOTAOutlineItem
-            parent = outlineItem.parent ?? KMBOTAOutlineItem()
-            index = Int(outlineItem.outline.index + 1)
+            outlineItem = outlineView.item(atRow: selectRowIndexs.last ?? 0) as? KMBOTAOutlineItem
+            parent = outlineItem?.parent ?? KMBOTAOutlineItem()
+            index = Int((outlineItem?.outline.index) ?? 0 + 1)
         }
         
         self.addOutlineToIndex(index: index, parent: parent)
@@ -538,6 +709,10 @@ extension KMOutlineViewController {
         self.deleteOutline(outlineItems: data.children)
         self.BOTAOutlineView.reloadData(expandItemType: .none)
     }
+    
+    @objc private func _searchAction() {
+        _showHeaderSearch()
+    }
 }
 
 //MARK: -  Action
@@ -571,15 +746,15 @@ extension KMOutlineViewController {
         }
     }
     
-    func addOutlineToIndex(index: Int, parent: KMBOTAOutlineItem) {
-        let pageIndex: Int = self.handdler.currentPageIndex
-        let label: String = self.fetchCurrentLabel(pageIndex: pageIndex)
+    func addOutlineToIndex(index: Int, parent: KMBOTAOutlineItem?) {
+        let pageIndex = self.handdler.currentPageIndex
+        let label = self.fetchCurrentLabel(pageIndex: pageIndex)
         let destination = self.handdler.currentDestination()
     
         self.addOutlineToIndex(index: index, pageIndex: pageIndex, destination: destination, lable: label, parent: parent)
     }
     
-    func addOutlineToIndex(index: Int, pageIndex: Int, destination: CPDFDestination?, lable: String, parent: KMBOTAOutlineItem) {
+    func addOutlineToIndex(index: Int, pageIndex: Int, destination: CPDFDestination?, lable: String, parent: KMBOTAOutlineItem?) {
         let outlineItem = KMBOTAOutlineItem()
         outlineItem.destination = destination
         outlineItem.label = lable
@@ -860,10 +1035,10 @@ extension KMOutlineViewController: NSMenuDelegate, NSMenuItemValidation {
         }
         
         if (action == #selector(undo)) {
-//            return self.listView.undoManager?.canUndo ?? false
+            return handdler.canUndo()
         }
         if (action == #selector(redo)) {
-//            return self.listView.undoManager?.canRedo ?? false
+            return handdler.canRedo()
         }
         
         if (action == #selector(expandAllComments)) {
@@ -910,32 +1085,83 @@ extension KMOutlineViewController: NSMenuDelegate, NSMenuItemValidation {
 
 extension KMOutlineViewController: KMNOutlineHanddlerDelegate {
     func handdler(_ handdler: KMNOutlineHanddler, didAdd info: [String : Any]?) {
-        let items = info?["data"] as? [Any]
-        let outlineItem = items?.first
+        let tempOutlineItems = info?["data"] as? [KMBOTAOutlineItem] ?? []
         
-        let tempOutlineView = self.BOTAOutlineView!
-        var index = -1
-        if tempOutlineView.outlineView.numberOfRows == 1 || tempOutlineView.data == nil {
-            index = 0
+        let tempOutlineView = self.BOTAOutlineView
+        if tempOutlineView?.data?.children.count == 0 || tempOutlineView?.data == nil {
+            tempOutlineView?.inputData = self.handdler.outlineRoot()
         } else {
-            index = tempOutlineView.outlineView.row(forItem: outlineItem)
-        }
-
-        tempOutlineView.selectIndex(index: index)
-
-        //滑动到指定位置
-        if(tempOutlineView.outlineView.selectedRow >= 0) {
-            self.renameOutlineWithRow(row: tempOutlineView.outlineView.selectedRow)
+            tempOutlineView?.outlineView.reloadData()
         }
         
-        let row = tempOutlineView.outlineView.row(forItem: outlineItem)
-        if Thread.current.isMainThread {
-            tempOutlineView.outlineView.scrollToVisible(tempOutlineView.outlineView.rect(ofRow: row))
-        } else {
-            DispatchQueue.main.async {
-                tempOutlineView.outlineView.scrollToVisible(tempOutlineView.outlineView.rect(ofRow: row))
+        //展开
+//        DispatchQueue.main.async {
+            for outlineItem in tempOutlineItems {
+                var tempParent = outlineItem
+                while tempParent.parent != nil {
+                    tempParent.isItemExpanded = true
+                    tempParent = tempParent.parent!
+                    tempOutlineView?.outlineView.expandItem(tempParent)
+                }
+                tempOutlineView?.outlineView.expandItem(tempParent.parent)
             }
+//        }
+        
+        self.updateExtempViewState()
+    }
+    
+    func handdler(_ handdler: KMNOutlineHanddler, didRemove info: [String : Any]?) {
+        let tempOutlineItems = info?["data"] as? [KMBOTAOutlineItem] ?? []
+        let tempOutlineView = self.BOTAOutlineView
+        //展开
+        for outlineItem in tempOutlineItems {
+            outlineItem.parent?.isItemExpanded = true
+            tempOutlineView?.outlineView.expandItem(outlineItem.parent)
+        }
+        
+        tempOutlineView?.outlineView.reloadData()
+        //删除需要取消选中
+        tempOutlineView?.cancelSelect()
+        
+        //刷新nil数据
+        self.updateExtempViewState()
+    }
+    
+    func handdler(_ handdler: KMNOutlineHanddler, didRename outline: CPDFOutline?, info: [String : Any]?) {
+        let outlineItem = info?["data"] as? KMBOTAOutlineItem
+        let tempOutlineView = self.BOTAOutlineView
+        
+        tempOutlineView?.outlineView.reloadItem(outlineItem)
+    }
+    
+    func handdler(_ handdler: KMNOutlineHanddler, didChangeLocation outline: CPDFOutline?, info: [String : Any]?) {
+        let outlineItem = info?["data"] as? KMBOTAOutlineItem
+        let tempOutlineView = self.BOTAOutlineView
+        
+        tempOutlineView?.outlineView.reloadItem(outlineItem)
+    }
+    
+    func handdler(_ handdler: KMNOutlineHanddler, didMove outline: CPDFOutline?, info: [String : Any]?) {
+        guard let outlineItem = info?["data"] as? KMBOTAOutlineItem else {
+            return
         }
+        
+        let parent = info?["parent"] as? KMBOTAOutlineItem
+        let tempOutlineView = self.BOTAOutlineView
+        let index = info?["index"] as? Int ?? 0
+        
+        //显示数据刷新
+        outlineItem.parent?.children.removeObject(outlineItem)
+        parent?.children.insert(outlineItem, at: index)
+        outlineItem.parent = parent
+        tempOutlineView?.outlineView.reloadData()
+        tempOutlineView?.cancelSelect()
+        
+        //展开
+        outlineItem.isItemExpanded = true
+        outlineItem.parent?.isItemExpanded = true
+        tempOutlineView?.outlineView.expandItem(outlineItem)
+        tempOutlineView?.outlineView.expandItem(outlineItem.parent)
     }
 }
 
@@ -949,27 +1175,29 @@ extension KMOutlineViewController {
 //MARK: - undoRedo
 extension KMOutlineViewController {
     func moveOutline(outlineItem: KMBOTAOutlineItem, index: NSInteger, parent: KMBOTAOutlineItem!) {
-        let tempOutlineView = self.BOTAOutlineView!
+//        let tempOutlineView = self.BOTAOutlineView!
         
-        let indexTemp = outlineItem.outline.index
-        let parentTemp = outlineItem.parent
+//        let indexTemp = outlineItem.outline.index
+//        let parentTemp = outlineItem.parent
         
         //元数据移除
-        outlineItem.outline.removeFromParent()
-        parent.outline.insertChild(outlineItem.outline, at: UInt(index))
+//        outlineItem.outline.removeFromParent()
+//        parent.outline.insertChild(outlineItem.outline, at: UInt(index))
         
-        //显示数据刷新
-        outlineItem.parent?.children.removeObject(outlineItem)
-        parent?.children.insert(outlineItem, at: index)
-        outlineItem.parent = parent
-        tempOutlineView.outlineView.reloadData()
-        tempOutlineView.cancelSelect()
-        
-        //展开
-        outlineItem.isItemExpanded = true
-        outlineItem.parent?.isItemExpanded = true
-        tempOutlineView.outlineView.expandItem(outlineItem)
-        tempOutlineView.outlineView.expandItem(outlineItem.parent)
+        handdler.moveOutline(outlineItem: outlineItem, index: index, parent: parent)
+//
+//        //显示数据刷新
+//        outlineItem.parent?.children.removeObject(outlineItem)
+//        parent?.children.insert(outlineItem, at: index)
+//        outlineItem.parent = parent
+//        tempOutlineView.outlineView.reloadData()
+//        tempOutlineView.cancelSelect()
+//
+//        //展开
+//        outlineItem.isItemExpanded = true
+//        outlineItem.parent?.isItemExpanded = true
+//        tempOutlineView.outlineView.expandItem(outlineItem)
+//        tempOutlineView.outlineView.expandItem(outlineItem.parent)
         
 //        self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
 //            self?.moveOutline(outlineItem: outlineItem, index: NSInteger(indexTemp), parent: parentTemp)
@@ -977,11 +1205,12 @@ extension KMOutlineViewController {
     }
     
     func changeLocation(outlineItem: KMBOTAOutlineItem, destination: CPDFDestination) {
-        let tempOutlineView = self.BOTAOutlineView!
+//        let tempOutlineView = self.BOTAOutlineView!
         
-        let temp = outlineItem.outline.destination
-        outlineItem.outline.destination = CPDFDestination(document: destination.document, pageIndex: destination.pageIndex, at: destination.point, zoom: destination.zoom)
-        tempOutlineView.outlineView.reloadItem(outlineItem)
+//        let temp = outlineItem.outline.destination
+//        outlineItem.outline.destination = CPDFDestination(document: destination.document, pageIndex: destination.pageIndex, at: destination.point, zoom: destination.zoom)
+        handdler.changeLocation(outlineItem: outlineItem, destination: destination)
+//        tempOutlineView.outlineView.reloadItem(outlineItem)
         
 //        self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
 //            self?.changeLocation(outlineItem: outlineItem, destination: temp!)
@@ -996,9 +1225,10 @@ extension KMOutlineViewController {
         if outlineItem.outline.label == label {
             return
         }
-        let temp: String = outlineItem.outline.label
-        outlineItem.outline.label = label
-        tempOutlineView.outlineView.reloadItem(outlineItem)
+//        let temp: String = outlineItem.outline.label
+//        outlineItem.outline.label = label
+        handdler.renamePDFOutline(outlineItem: outlineItem, label: label)
+//        tempOutlineView.outlineView.reloadItem(outlineItem)
         
 //        self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
 //            self?.renamePDFOutline(outlineItem: outlineItem, label: temp)
@@ -1009,28 +1239,30 @@ extension KMOutlineViewController {
         NSApp.mainWindow?.makeFirstResponder(self.BOTAOutlineView)
         let tempOutlineView = self.BOTAOutlineView!
         
-        var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems
-        tempOutlineItems.sort(){$0.toIndex > $1.toIndex}
-        
-        for outlineItem in tempOutlineItems {
-            outlineItem.outline.removeFromParent()
-            let index = outlineItem.parent?.children.firstIndex(of: outlineItem)
-            outlineItem.toIndex = index!
-            outlineItem.parent?.children.removeObject(outlineItem)
-        }
-        
-        //展开
-        for outlineItem in tempOutlineItems {
-            outlineItem.parent?.isItemExpanded = true
-            tempOutlineView.outlineView.expandItem(outlineItem.parent)
-        }
+//        var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems
+//        tempOutlineItems.sort(){$0.toIndex > $1.toIndex}
+//
+//        for outlineItem in tempOutlineItems {
+//            outlineItem.outline.removeFromParent()
+//            let index = outlineItem.parent?.children.firstIndex(of: outlineItem)
+//            outlineItem.toIndex = index!
+//            outlineItem.parent?.children.removeObject(outlineItem)
+//        }
         
-        tempOutlineView.outlineView.reloadData()
-        //删除需要取消选中
-        tempOutlineView.cancelSelect()
+        handdler.deleteOutline(outlineItems: outlineItems)
         
-        //刷新nil数据
-        self.updateExtempViewState()
+//        //展开
+//        for outlineItem in tempOutlineItems {
+//            outlineItem.parent?.isItemExpanded = true
+//            tempOutlineView.outlineView.expandItem(outlineItem.parent)
+//        }
+//
+//        tempOutlineView.outlineView.reloadData()
+//        //删除需要取消选中
+//        tempOutlineView.cancelSelect()
+//
+//        //刷新nil数据
+//        self.updateExtempViewState()
 //        self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
 //            self?.addOutline(outlineItems: tempOutlineItems)
 //        }
@@ -1045,53 +1277,50 @@ extension KMOutlineViewController {
         var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems
         tempOutlineItems.sort(){$0.toIndex < $1.toIndex}
         
-        for outlineItem in tempOutlineItems {
-            if outlineItem.outline.label != nil {
-                outlineItem.parent?.outline.insertChild(outlineItem.outline, at: UInt(outlineItem.toIndex))
-            } else {
-                let outline = outlineItem.parent?.outline.insertChild(at: UInt(outlineItem.toIndex))
-                outline?.label = outlineItem.label
-                outline?.destination = outlineItem.destination
-                outlineItem.outline = outline!
-            }
-            outlineItem.parent?.children.insert(outlineItem, at: outlineItem.toIndex)
-        }
-        
-        if tempOutlineView.data?.children.count == 0 || tempOutlineView.data == nil {
-            tempOutlineView.inputData = self.handdler.outlineRoot()
-        } else {
-            tempOutlineView.outlineView.reloadData()
-        }
-        
-        //展开
-//        DispatchQueue.main.async {
-            for outlineItem in tempOutlineItems {
-                var tempParent = outlineItem
-                while tempParent.parent != nil {
-                    tempParent.isItemExpanded = true
-                    tempParent = tempParent.parent!
-                    tempOutlineView.outlineView.expandItem(tempParent)
-                }
-                tempOutlineView.outlineView.expandItem(tempParent.parent)
-            }
+        handdler.addOutline(outlineItems: tempOutlineItems)
+//        for outlineItem in tempOutlineItems {
+//            if outlineItem.outline.label != nil {
+//                outlineItem.parent?.outline.insertChild(outlineItem.outline, at: UInt(outlineItem.toIndex))
+//            } else {
+//                let outline = outlineItem.parent?.outline.insertChild(at: UInt(outlineItem.toIndex))
+//                outline?.label = outlineItem.label
+//                outline?.destination = outlineItem.destination
+//                outlineItem.outline = outline!
+//            }
+//            outlineItem.parent?.children.insert(outlineItem, at: outlineItem.toIndex)
 //        }
         
-        self.updateExtempViewState()
+//        if tempOutlineView.data?.children.count == 0 || tempOutlineView.data == nil {
+//            tempOutlineView.inputData = self.handdler.outlineRoot()
+//        } else {
+//            tempOutlineView.outlineView.reloadData()
+//        }
+//
+//        //展开
+////        DispatchQueue.main.async {
+//            for outlineItem in tempOutlineItems {
+//                var tempParent = outlineItem
+//                while tempParent.parent != nil {
+//                    tempParent.isItemExpanded = true
+//                    tempParent = tempParent.parent!
+//                    tempOutlineView.outlineView.expandItem(tempParent)
+//                }
+//                tempOutlineView.outlineView.expandItem(tempParent.parent)
+//            }
+////        }
+//
+//        self.updateExtempViewState()
 //        self.listView.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
 //            self?.deleteOutline(outlineItems: tempOutlineItems)
 //        }
     }
     
     @IBAction func undo(_ sender: Any) {
-//        if (self.listView.undoManager?.canUndo ?? false) {
-//            self.listView.undoManager?.undo()
-//        }
+        handdler.undo()
     }
     
     @IBAction func redo(_ sender: Any) {
-//        if (self.listView.undoManager?.canRedo ?? false) {
-//            self.listView.undoManager?.redo()
-//        }
+        handdler.redo()
     }
 }
 
@@ -1151,6 +1380,8 @@ extension KMOutlineViewController: ComponentGroupDelegate {
                 } else if index == 11 {
                     demoteItemAction()
                 }
+                
+                group?.removeFromSuperview()
             }
         }
     }

+ 85 - 25
PDF Office/PDF Master/KMClass/Left/Outline/Tools/KMNOutlineHanddler.swift

@@ -11,7 +11,10 @@ import Cocoa
     @objc optional func handdler(_ handdler: KMNOutlineHanddler, didAdd info: [String : Any]?)
     @objc optional func handdler(_ handdler: KMNOutlineHanddler, didRemove info: [String : Any]?)
     
-//    @objc optional func handdler(_ handdler: KMNOutlineHanddler, didRename bookmark: CPDFBookmark?, info: [String : Any]?)
+    @objc optional func handdler(_ handdler: KMNOutlineHanddler, didRename outline: CPDFOutline?, info: [String : Any]?)
+    @objc optional func handdler(_ handdler: KMNOutlineHanddler, didChangeLocation outline: CPDFOutline?, info: [String : Any]?)
+    
+    @objc optional func handdler(_ handdler: KMNOutlineHanddler, didMove outline: CPDFOutline?, info: [String : Any]?)
 }
 
 class KMNOutlineHanddler: NSObject {
@@ -55,12 +58,27 @@ class KMNOutlineHanddler: NSObject {
         return pdfView?.currentDestination
     }
     
+    func canUndo() -> Bool {
+        return pdfView?.undoManager?.canUndo ?? false
+    }
+    
+    func canRedo() -> Bool {
+        return pdfView?.undoManager?.canRedo ?? false
+    }
+    
+    func undo() {
+        if canUndo() {
+            pdfView?.undoManager?.undo()
+        }
+    }
+    
+    func redo() {
+        if canRedo() {
+            pdfView?.undoManager?.redo()
+        }
+    }
+    
     func addOutline(outlineItems: [KMBOTAOutlineItem]) {
-//        NSApp.mainWindow?.makeFirstResponder(self.BOTAOutlineView)
-//        let tempOutlineView = self.BOTAOutlineView!
-        //先取消选中
-//        tempOutlineView.cancelSelect()
-        
         var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems
         tempOutlineItems.sort(){$0.toIndex < $1.toIndex}
         
@@ -78,28 +96,70 @@ class KMNOutlineHanddler: NSObject {
         
         delegate?.handdler?(self, didAdd: ["data": tempOutlineItems])
         
-//        if tempOutlineView.data?.children.count == 0 || tempOutlineView.data == nil {
-//            tempOutlineView.inputData = self.handdler.outlineRoot()
-//        } else {
-//            tempOutlineView.outlineView.reloadData()
-//        }
+        pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
+            self?.deleteOutline(outlineItems: tempOutlineItems)
+        }
+    }
+    
+    func deleteOutline(outlineItems: [KMBOTAOutlineItem]) {
+        var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems
+        tempOutlineItems.sort(){$0.toIndex > $1.toIndex}
+        
+        for outlineItem in tempOutlineItems {
+            outlineItem.outline.removeFromParent()
+            let index = outlineItem.parent?.children.firstIndex(of: outlineItem)
+            outlineItem.toIndex = index!
+            outlineItem.parent?.children.removeObject(outlineItem)
+        }
+        
+        delegate?.handdler?(self, didRemove: ["data" : tempOutlineItems])
+        
+        pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
+            self?.addOutline(outlineItems: tempOutlineItems)
+        }
+    }
+    
+    func renamePDFOutline(outlineItem: KMBOTAOutlineItem!, label: String) {
+        if outlineItem.outline.label == label {
+            return
+        }
+        let temp: String = outlineItem.outline.label
+        outlineItem.outline.label = label
+        
+        delegate?.handdler?(self, didRename: outlineItem.outline, info: ["data" : outlineItem])
+        
+        pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
+            self?.renamePDFOutline(outlineItem: outlineItem, label: temp)
+        }
+    }
+    
+    func changeLocation(outlineItem: KMBOTAOutlineItem, destination: CPDFDestination) {
+        let temp = outlineItem.outline.destination
+        outlineItem.outline.destination = CPDFDestination(document: destination.document, pageIndex: destination.pageIndex, at: destination.point, zoom: destination.zoom)
+        
+        delegate?.handdler?(self, didChangeLocation: outlineItem.outline, info: ["data" : outlineItem])
+        
+        pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
+            if let data = temp {
+                self?.changeLocation(outlineItem: outlineItem, destination: data)
+            }
+        }
+    }
+    
+    func moveOutline(outlineItem: KMBOTAOutlineItem, index: NSInteger, parent: KMBOTAOutlineItem!) {
+//        let tempOutlineView = self.BOTAOutlineView!
+        
+        let indexTemp = outlineItem.outline.index
+        let parentTemp = outlineItem.parent
+        
+        //元数据移除
+        outlineItem.outline.removeFromParent()
+        parent.outline.insertChild(outlineItem.outline, at: UInt(index))
         
-        //展开
-//        DispatchQueue.main.async {
-//            for outlineItem in tempOutlineItems {
-//                var tempParent = outlineItem
-//                while tempParent.parent != nil {
-//                    tempParent.isItemExpanded = true
-//                    tempParent = tempParent.parent!
-//                    tempOutlineView.outlineView.expandItem(tempParent)
-//                }
-//                tempOutlineView.outlineView.expandItem(tempParent.parent)
-//            }
-//        }
+        delegate?.handdler?(self, didMove: outlineItem.outline, info: ["data" : outlineItem, "parent" : parent, "index" : index])
         
-//        self.updateExtempViewState()
         pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in
-//            self?.deleteOutline(outlineItems: tempOutlineItems)
+            self?.moveOutline(outlineItem: outlineItem, index: NSInteger(indexTemp), parent: parentTemp)
         }
     }
 

+ 108 - 0
PDF Office/PDF Master/KMClass/Left/Outline/View/KMNBotaHeaderSearchView.swift

@@ -0,0 +1,108 @@
+//
+//  KMNBotaHeaderSearchView.swift
+//  PDF Reader Pro
+//
+//  Created by User-Tangchao on 2024/11/13.
+//
+
+import Cocoa
+import KMComponentLibrary
+
+class KMNBotaHeaderSearchView: NSView, NibLoadable {
+    @IBOutlet weak var leftBox: NSBox!
+    @IBOutlet weak var searchBox: NSBox!
+    @IBOutlet weak var rightBox: NSBox!
+    
+    @IBOutlet weak var bottomLine: NSView!
+    
+    var itemClick: KMCommonClickBlock?
+    var valueDidChange: KMValueDidChangeBlock?
+    
+    private var groupView_: ComponentGroup?
+    
+    private lazy var searchButton_: ComponentButton = {
+        let view = ComponentButton()
+        view.properties = ComponentButtonProperty(type: .text_gray, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearch"))
+        return view
+    }()
+    
+    private lazy var input_: ComponentInput = {
+        let view = ComponentInput()
+        view.properties = ComponentInputProperty(size: .s, placeholder: KMLocalizedString("Search"), text: "")
+        return view
+    }()
+    
+    private lazy var closeButton_: ComponentButton = {
+        let view = ComponentButton()
+        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaClose"))
+        return view
+    }()
+    
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+
+        // Drawing code here.
+    }
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+        leftBox.borderWidth = 0
+        leftBox.contentView = searchButton_
+        searchButton_.setTarget(self, action: #selector(_searchAction))
+        
+        searchBox.borderWidth = 0
+        searchBox.contentView = input_
+        input_.delegate = self
+        
+        rightBox.borderWidth = 0
+        rightBox.contentView = closeButton_
+        closeButton_.setTarget(self, action: #selector(_closeAction))
+    }
+    
+    @objc private func _searchAction() {
+        var viewHeight: CGFloat = 8
+        var menuItemArr: [ComponentMenuitemProperty] = []
+        let titles = ["Ignore Case"]
+        for i in titles {
+            let menuI: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false, itemSelected: false, isDisabled: false, keyEquivalent: nil, text: KMLocalizedString(i))
+            menuItemArr.append(menuI)
+            viewHeight += 36
+        }
+        
+        if groupView_ == nil {
+            groupView_ = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
+        }
+        groupView_?.groupDelegate = self
+        groupView_?.frame = CGRectMake(310, 0, 200, viewHeight)
+        groupView_?.updateGroupInfo(menuItemArr)
+        
+        var point = searchButton_.convert(searchButton_.frame.origin, to: nil)
+        point.y -= viewHeight
+        groupView_?.showWithPoint(point, relativeTo: searchButton_)
+        
+        searchButton_.properties.state = .pressed
+        searchButton_.reloadData()
+    }
+    
+    @objc private func _closeAction() {
+        itemClick?(2)
+    }
+}
+
+extension KMNBotaHeaderSearchView: ComponentInputDelegate {
+    func componentInputDidChanged(inputView: ComponentInput) {
+        valueDidChange?(inputView, [.newKey : inputView.properties.text])
+    }
+}
+
+extension KMNBotaHeaderSearchView: ComponentGroupDelegate {
+    func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
+        itemClick?(1)
+    }
+    
+    func componentGroupDidDismiss(group: ComponentGroup?) {
+        searchButton_.properties.state = .normal
+        searchButton_.reloadData()
+    }
+}

+ 76 - 0
PDF Office/PDF Master/KMClass/Left/Outline/View/KMNBotaHeaderSearchView.xib

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView id="c22-O7-iKe" customClass="KMNBotaHeaderSearchView" customModule="PDF_Reader_Pro" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="480" height="40"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+            <subviews>
+                <box boxType="custom" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="yRL-mq-0w7">
+                    <rect key="frame" x="11" y="11" width="18" height="18"/>
+                    <view key="contentView" id="yqT-Ht-T7H">
+                        <rect key="frame" x="1" y="1" width="16" height="16"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </view>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="18" id="U5C-xB-czx"/>
+                        <constraint firstAttribute="height" constant="18" id="bCg-wx-ATf"/>
+                    </constraints>
+                </box>
+                <box boxType="custom" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="wHN-nZ-y7R">
+                    <rect key="frame" x="36" y="10" width="400" height="20"/>
+                    <view key="contentView" id="Tcq-Ry-qfX">
+                        <rect key="frame" x="1" y="1" width="398" height="18"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </view>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="WpT-2x-wuB"/>
+                    </constraints>
+                </box>
+                <box boxType="custom" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="XEG-JI-KNA">
+                    <rect key="frame" x="444" y="8" width="24" height="24"/>
+                    <view key="contentView" id="f8C-WF-bvn">
+                        <rect key="frame" x="1" y="1" width="22" height="22"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    </view>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="24" id="IAt-j6-MA3"/>
+                        <constraint firstAttribute="height" constant="24" id="R6Z-Hh-eqN"/>
+                    </constraints>
+                </box>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="m70-PN-kAN">
+                    <rect key="frame" x="0.0" y="0.0" width="480" height="2"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="2" id="xxU-cv-B9D"/>
+                    </constraints>
+                </customView>
+            </subviews>
+            <constraints>
+                <constraint firstItem="yRL-mq-0w7" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" constant="11" id="0Qa-5k-aDW"/>
+                <constraint firstItem="wHN-nZ-y7R" firstAttribute="leading" secondItem="yRL-mq-0w7" secondAttribute="trailing" constant="7" id="89k-M7-fZL"/>
+                <constraint firstItem="wHN-nZ-y7R" firstAttribute="centerY" secondItem="c22-O7-iKe" secondAttribute="centerY" id="BpJ-Dd-N1q"/>
+                <constraint firstAttribute="trailing" secondItem="XEG-JI-KNA" secondAttribute="trailing" constant="12" id="BzV-Jm-ZhE"/>
+                <constraint firstItem="m70-PN-kAN" firstAttribute="leading" secondItem="c22-O7-iKe" secondAttribute="leading" id="Efg-zt-oCZ"/>
+                <constraint firstAttribute="bottom" secondItem="m70-PN-kAN" secondAttribute="bottom" id="K9m-cj-2gx"/>
+                <constraint firstAttribute="trailing" secondItem="m70-PN-kAN" secondAttribute="trailing" id="LBY-YD-L7V"/>
+                <constraint firstItem="XEG-JI-KNA" firstAttribute="leading" secondItem="wHN-nZ-y7R" secondAttribute="trailing" constant="8" id="M3I-jY-xHC"/>
+                <constraint firstItem="yRL-mq-0w7" firstAttribute="centerY" secondItem="c22-O7-iKe" secondAttribute="centerY" id="dOh-Hx-MRh"/>
+                <constraint firstItem="XEG-JI-KNA" firstAttribute="centerY" secondItem="c22-O7-iKe" secondAttribute="centerY" id="v2x-IN-NOS"/>
+            </constraints>
+            <connections>
+                <outlet property="bottomLine" destination="m70-PN-kAN" id="HzX-Zf-Heh"/>
+                <outlet property="leftBox" destination="yRL-mq-0w7" id="9Uf-XO-oVf"/>
+                <outlet property="rightBox" destination="XEG-JI-KNA" id="8nv-e2-DvK"/>
+                <outlet property="searchBox" destination="wHN-nZ-y7R" id="lyq-51-pqg"/>
+            </connections>
+            <point key="canvasLocation" x="156" y="-67"/>
+        </customView>
+    </objects>
+</document>

+ 22 - 1
PDF Office/PDF Master/KMClass/Tools/Tool/KMNColorTools.swift

@@ -9,18 +9,39 @@ import Cocoa
 import KMComponentLibrary
 
 class KMNColorTools: NSObject {
-    
+    // MARK: - Text Color
     // colorText-1 colorText/1
     @inline (__always) class func colorText_1() -> NSColor {
         return ComponentLibrary.shared.getComponentColorFromKey("colorText/1")
     }
     
+    @inline (__always) class func colorText_2() -> NSColor {
+        return ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
+    }
+    
+    // MARK: - bg Color
+    
     @inline (__always) class func colorBg_popup() -> NSColor {
         return ComponentLibrary.shared.getComponentColorFromKey("colorBg/popup")
     }
     
+    @inline (__always) class func colorBg_layoutMiddle() -> NSColor {
+        return ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle")
+    }
+    
+    // MARK: - fill Color
+    
     @inline (__always) class func compField_colorTextFilledNor() -> NSColor {
         return ComponentLibrary.shared.getComponentColorFromKey("comp-field/colorText-filled-nor")
     }
     
+    // MARK: - border Color
+    
+    @inline (__always) class func colorBorder_divider() -> NSColor {
+        return ComponentLibrary.shared.getComponentColorFromKey("colorBorder/divider")
+    }
+    
+    @inline (__always) class func colorPrimary_border1() -> NSColor {
+        return ComponentLibrary.shared.getComponentColorFromKey("colorPrimary/border1")
+    }
 }

+ 16 - 0
PDF Office/PDF Reader Pro.xcodeproj/project.pbxproj

@@ -86,6 +86,12 @@
 		65202DF12CE46DA700A204B5 /* KMNColorTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF02CE46DA700A204B5 /* KMNColorTools.swift */; };
 		65202DF22CE46DA700A204B5 /* KMNColorTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF02CE46DA700A204B5 /* KMNColorTools.swift */; };
 		65202DF32CE46DA700A204B5 /* KMNColorTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF02CE46DA700A204B5 /* KMNColorTools.swift */; };
+		65202DF72CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF62CE4803500A204B5 /* KMNBotaHeaderSearchView.swift */; };
+		65202DF82CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF62CE4803500A204B5 /* KMNBotaHeaderSearchView.swift */; };
+		65202DF92CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65202DF62CE4803500A204B5 /* KMNBotaHeaderSearchView.swift */; };
+		65202DFC2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65202DFB2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib */; };
+		65202DFD2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65202DFB2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib */; };
+		65202DFE2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 65202DFB2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib */; };
 		652E953D2C6670CE0061FA40 /* KMFreehandAnnotationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652E953C2C6670CE0061FA40 /* KMFreehandAnnotationController.swift */; };
 		652E953E2C6670CE0061FA40 /* KMFreehandAnnotationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652E953C2C6670CE0061FA40 /* KMFreehandAnnotationController.swift */; };
 		652E953F2C6670CE0061FA40 /* KMFreehandAnnotationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 652E953C2C6670CE0061FA40 /* KMFreehandAnnotationController.swift */; };
@@ -6023,6 +6029,8 @@
 		651675E12CE3313400019A20 /* KMOutlineViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KMOutlineViewController.swift; sourceTree = "<group>"; };
 		651675E22CE3313500019A20 /* KMOutlineEditViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KMOutlineEditViewController.xib; sourceTree = "<group>"; };
 		65202DF02CE46DA700A204B5 /* KMNColorTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMNColorTools.swift; sourceTree = "<group>"; };
+		65202DF62CE4803500A204B5 /* KMNBotaHeaderSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMNBotaHeaderSearchView.swift; sourceTree = "<group>"; };
+		65202DFB2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMNBotaHeaderSearchView.xib; sourceTree = "<group>"; };
 		652E953C2C6670CE0061FA40 /* KMFreehandAnnotationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMFreehandAnnotationController.swift; sourceTree = "<group>"; };
 		652E95412C6913C20061FA40 /* KMLineAndBorderItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMLineAndBorderItemView.swift; sourceTree = "<group>"; };
 		652E95512C6914770061FA40 /* KMLineAndBorderItemView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMLineAndBorderItemView.xib; sourceTree = "<group>"; };
@@ -8570,6 +8578,8 @@
 				651675B92CE3311F00019A20 /* KMBOTAOutlineRowView.swift */,
 				651675BA2CE3311F00019A20 /* KMTocOutlineView.swift */,
 				651675BB2CE3311F00019A20 /* KMBOTAOutlineView.swift */,
+				65202DF62CE4803500A204B5 /* KMNBotaHeaderSearchView.swift */,
+				65202DFB2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -16385,6 +16395,7 @@
 				BB276A5C2B038D3A00AB5578 /* KMOCRPDFWindowController.xib in Resources */,
 				BBC70EA92AEA6EF800AC1585 /* KMToolbarCustomWindowController.xib in Resources */,
 				BBFA1CE62B60DDC50053AD4A /* KMScreenShotEditViewController.xib in Resources */,
+				65202DFC2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */,
 				BB328B6D2B565BEC00B382C6 /* iVersion.bundle in Resources */,
 				ADFCEB612B4FBFC50001EBAF /* ad_cancel_button00@4x.png in Resources */,
 				651675BE2CE3312000019A20 /* KMBOTAOutlineCellView.xib in Resources */,
@@ -16804,6 +16815,7 @@
 				AD199DEC2B230B1300D56FEE /* KMPrintMultipageView.xib in Resources */,
 				9FE0BBE82B0EFBA300CD1CAC /* KMAnnotationFontWindowController.xib in Resources */,
 				BBE788FA2CBD2464008086E2 /* ProgressVC.xib in Resources */,
+				65202DFD2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */,
 				ADAFDA1D2AE8DD6600F084BC /* KMAdvertisementTableView.xib in Resources */,
 				9F8810992B56877C00F69815 /* KMAnnotationChoiceWidgetOptionsViewController.xib in Resources */,
 				9F0CB4B92977BC1000007028 /* KMPropertiesPanelPreviewSubVC.xib in Resources */,
@@ -17568,6 +17580,7 @@
 				9F0CB4642966C9E200007028 /* KMFormPropertPanelViewController.xib in Resources */,
 				651675C02CE3312000019A20 /* KMBOTAOutlineCellView.xib in Resources */,
 				6536FDED2C9C49C1004A0FB9 /* KMNoteFooterCellView.xib in Resources */,
+				65202DFE2CE4827900A204B5 /* KMNBotaHeaderSearchView.xib in Resources */,
 				BBB789B62BE8BF2400F7E09C /* AIChatStringUploadItem.xib in Resources */,
 				BBFBE74B28DD7DDE008B2335 /* Main.storyboard in Resources */,
 				9F3A48CA2C8017FA0047F565 /* KMPurchaseEmbeddedWindowController.xib in Resources */,
@@ -18697,6 +18710,7 @@
 				89D2D2C5294972B900BFF5FE /* KMFormCellView.swift in Sources */,
 				AD7D5CA92B906E36006562CD /* CPDFListView+Sync.swift in Sources */,
 				BB6BA4C42B0B4A0F00462CAE /* KMLeftSideEmptyFileViewController.swift in Sources */,
+				65202DF72CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */,
 				F337CC2F2CC64BD600D46AF4 /* KMNPageEditViewController.swift in Sources */,
 				BB897224294B07960045787C /* KMWatermarkAdjectiveTopBarItemView.swift in Sources */,
 				AD3AAD1B2B0B5B4400DE5FE7 /* KMCompareCoveringWindowController.swift in Sources */,
@@ -19559,6 +19573,7 @@
 				BBE788E82CBD2464008086E2 /* CardVC.swift in Sources */,
 				BBF62C712B0347AF007B7E86 /* SplitWindowController.swift in Sources */,
 				9FAAA326290A69920046FFCE /* KMToolSetScroller.swift in Sources */,
+				65202DF82CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */,
 				BB89724E294C1DCE0045787C /* KMWatermarkAdjectiveListTableCellView.swift in Sources */,
 				BB14700F299DC0D100784A6A /* OIDScopes.m in Sources */,
 				9F0CB52E298656D900007028 /* KMDesignToken+BorderWidthRight.swift in Sources */,
@@ -20634,6 +20649,7 @@
 				ADD56F592BB3F48300E87ED9 /* KMFreeTextStylesViewController.m in Sources */,
 				BBFE6E772930E53000142C01 /* KMMergePopoverViewController.swift in Sources */,
 				ADF6B8782A48155E0090CB78 /* KMComparativeViewCollectionItem.swift in Sources */,
+				65202DF92CE4803500A204B5 /* KMNBotaHeaderSearchView.swift in Sources */,
 				BB65A07A2AF8E2F2003A27A0 /* KMSyncPreferences.swift in Sources */,
 				BB32BF252A5EA05900D11348 /* KMAnalytics.swift in Sources */,
 				ADAFDA1B2AE8DD6600F084BC /* KMAdvertisementTableView.swift in Sources */,