Browse Source

【2025】【BOTA】搜索列表UI处理

tangchao 3 months ago
parent
commit
6341c9ebcd
23 changed files with 1249 additions and 198 deletions
  1. 6 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/Contents.json
  2. 22 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/Contents.json
  3. 77 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/button 1.pdf
  4. 76 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/button.pdf
  5. 22 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/Contents.json
  6. 77 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/button.pdf
  7. 76 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/icon_prefix.pdf
  8. 22 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/Contents.json
  9. 60 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/icon_prefix 1.pdf
  10. 60 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/icon_prefix.pdf
  11. 22 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/Contents.json
  12. BIN
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/icon_prefix 1.pdf
  13. BIN
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/icon_prefix.pdf
  14. 22 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/Contents.json
  15. 81 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/prefix 1.pdf
  16. 80 0
      PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/prefix.pdf
  17. 275 48
      PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/Search/KMBotaSearchViewController.swift
  18. 12 145
      PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/Search/KMBotaSearchViewController.xib
  19. 2 0
      PDF Office/PDF Master/KMClass/Left/Search/Tools/KMNSearchHanddler.swift
  20. 162 5
      PDF Office/PDF Master/KMClass/Left/Search/View/KMNBotaSearchTopView.swift
  21. 83 0
      PDF Office/PDF Master/KMClass/Left/Search/View/KMNSearchReplaceItemView.swift
  22. 4 0
      PDF Office/PDF Master/KMClass/Tools/Tool/KMNColorTools.swift
  23. 8 0
      PDF Office/PDF Reader Pro.xcodeproj/project.pbxproj

+ 6 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/Contents.json

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

+ 77 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/button 1.pdf

@@ -0,0 +1,77 @@
+%PDF-1.7
+
+1 0 obj
+  << /ExtGState << /E1 << /ca 0.500000 >> >> >>
+endobj
+
+2 0 obj
+  << /Length 3 0 R >>
+stream
+/DeviceRGB CS
+/DeviceRGB cs
+q
+/E1 gs
+1.000000 0.000000 -0.000000 1.000000 3.333984 5.203125 cm
+1.000000 1.000000 1.000000 scn
+0.195262 5.268605 m
+0.455612 5.528955 0.877722 5.528955 1.138071 5.268605 c
+4.666667 1.740009 l
+8.195263 5.268605 l
+8.455612 5.528955 8.877722 5.528955 9.138071 5.268605 c
+9.398421 5.008255 9.398421 4.586145 9.138071 4.325796 c
+5.138071 0.325796 l
+4.877722 0.065446 4.455612 0.065446 4.195262 0.325796 c
+0.195262 4.325796 l
+-0.065087 4.586145 -0.065087 5.008255 0.195262 5.268605 c
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  517
+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
+0000000074 00000 n
+0000000647 00000 n
+0000000669 00000 n
+0000000842 00000 n
+0000000916 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+975
+%%EOF

+ 76 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchNext.imageset/button.pdf

@@ -0,0 +1,76 @@
+%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.333496 5.203125 cm
+0.533333 0.549020 0.580392 scn
+0.195262 5.268605 m
+0.455612 5.528955 0.877722 5.528955 1.138071 5.268605 c
+4.666667 1.740009 l
+8.195263 5.268605 l
+8.455612 5.528955 8.877722 5.528955 9.138071 5.268605 c
+9.398421 5.008255 9.398421 4.586145 9.138071 4.325796 c
+5.138071 0.325796 l
+4.877722 0.065446 4.455612 0.065446 4.195262 0.325796 c
+0.195262 4.325796 l
+-0.065087 4.586145 -0.065087 5.008255 0.195262 5.268605 c
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  510
+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
+0000000600 00000 n
+0000000622 00000 n
+0000000795 00000 n
+0000000869 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+928
+%%EOF

+ 22 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/Contents.json

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

+ 77 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/button.pdf

@@ -0,0 +1,77 @@
+%PDF-1.7
+
+1 0 obj
+  << /ExtGState << /E1 << /ca 0.250000 >> >> >>
+endobj
+
+2 0 obj
+  << /Length 3 0 R >>
+stream
+/DeviceRGB CS
+/DeviceRGB cs
+q
+/E1 gs
+1.000000 0.000000 -0.000000 1.000000 3.333984 5.203125 cm
+1.000000 1.000000 1.000000 scn
+4.195262 5.268605 m
+4.455612 5.528955 4.877722 5.528955 5.138071 5.268605 c
+9.138071 1.268605 l
+9.398421 1.008255 9.398421 0.586145 9.138071 0.325796 c
+8.877722 0.065446 8.455612 0.065446 8.195263 0.325796 c
+4.666667 3.854392 l
+1.138071 0.325796 l
+0.877722 0.065446 0.455612 0.065446 0.195262 0.325796 c
+-0.065087 0.586145 -0.065087 1.008255 0.195262 1.268605 c
+4.195262 5.268605 l
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  517
+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
+0000000074 00000 n
+0000000647 00000 n
+0000000669 00000 n
+0000000842 00000 n
+0000000916 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+975
+%%EOF

+ 76 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchPreviousDisable.imageset/icon_prefix.pdf

@@ -0,0 +1,76 @@
+%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.333496 5.203125 cm
+0.717647 0.729412 0.749020 scn
+4.195262 5.267629 m
+4.455612 5.527978 4.877722 5.527978 5.138071 5.267629 c
+9.138071 1.267628 l
+9.398421 1.007279 9.398421 0.585169 9.138071 0.324820 c
+8.877722 0.064470 8.455612 0.064470 8.195263 0.324820 c
+4.666667 3.853415 l
+1.138071 0.324820 l
+0.877722 0.064470 0.455612 0.064470 0.195262 0.324820 c
+-0.065087 0.585169 -0.065087 1.007279 0.195262 1.267628 c
+4.195262 5.267629 l
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  510
+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
+0000000600 00000 n
+0000000622 00000 n
+0000000795 00000 n
+0000000869 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+928
+%%EOF

+ 22 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/Contents.json

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

+ 60 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/icon_prefix 1.pdf

@@ -0,0 +1,60 @@
+%PDF-1.7
+
+1 0 obj
+  << >>
+endobj
+
+2 0 obj
+  << /Filter /FlateDecode
+     /Length 3 0 R
+  >>
+stream
+x•“MŠ1…÷>E­£±~,[Û$�u’#è9ž‹n¹ 
a¼©×_ÉÒ“TýüùåϯýåÛ—�Û§ïåyýÚßÊïÂT�³Õ»xJ•ï–¨ÖtÛ¯ëê¿âm-,dÞ‘1¦êök9ä}ª	/i›VUÞžY
�T“Ž}�öR~–ÊkùúÿoÈIŽØ�_‹’‹»õä{ÊA£«6Y$Sì%=%»,Ô+÷1íõ"HšF3~¡½Š.æ(•†dxS›[ë-ºñ|Ëfìoª*>pоõ	q`ePPö�¡1<†Ü¢Ø‚Ÿa�Ž
*±ö@åNÁ¨[p‡sj$ÑŽE.|ïäŠÊÇ$u±uçÁ2ÅÑÜ!O¦ÞæË·‰÷X_MÆ'Ù±í&½é)
+Cf5wˆnUÚ|¥­
|µFìÞUpo†‹UÛÚd 0a„ELùˆ¡©ã€	‰+2Ÿ™såÆð¯.µ
k£VË	¥ÿ$sº·¿É_²ÄË
+endstream
+endobj
+
+3 0 obj
+  387
+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
+0000000505 00000 n
+0000000527 00000 n
+0000000700 00000 n
+0000000774 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+833
+%%EOF

+ 60 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchReplace.imageset/icon_prefix.pdf

@@ -0,0 +1,60 @@
+%PDF-1.7
+
+1 0 obj
+  << >>
+endobj
+
+2 0 obj
+  << /Filter /FlateDecode
+     /Length 3 0 R
+  >>
+stream
+x•“MŠ1…÷>…×�ñX¿¶¶I ë$G(&$Ð=rþ<›n»
ÃxS¯¿’¥'©ëùëË¿?ÇË�oŸó—Ÿéyÿ:ÞÒßD¥Î“ë]<-µÞmQKH¨I>®	qÎMm\
%êdÞ]òÛñšˆ‹zxCƪuÍ×4å„>Ô€—„´&U„ò“­A,ƒÊ¢ýD¤½¤ßéקôš¾¸#.†Äû
yá›iݾ&)ÎîÚN�î){éMÄx“•âÅæÙì²Y”V©õa¯EgFÒetÅot¤^¢±:J-CÜÝDÇÖšESoI•<àMDØ;îj ÀsVz©J24†çdÈÍ‚-øF‘Ýà”†Y"MPêÁÜáœYèÀ"7¾wrEå9IÙlßy°�•b67å	Âô‚·ùÒmâ-°rpœ¿È�m7“S†L¢îM+Ûx%fÿZ-äÞ„qo„³VÍ6(LhÁ"†|ÄÐÔ<`\Ø™ÏL
+Q%#øçjŬ׊bkBËÿ"cº·Ïä?�%Ì
+endstream
+endobj
+
+3 0 obj
+  399
+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
+0000000517 00000 n
+0000000539 00000 n
+0000000712 00000 n
+0000000786 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+845
+%%EOF

+ 22 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/Contents.json

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

BIN
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/icon_prefix 1.pdf


BIN
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImageNameBotaSearchSwitch.imageset/icon_prefix.pdf


+ 22 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/Contents.json

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

+ 81 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/prefix 1.pdf

@@ -0,0 +1,81 @@
+%PDF-1.7
+
+1 0 obj
+  << /ExtGState << /E1 << /ca 0.800000 >> >> >>
+endobj
+
+2 0 obj
+  << /Length 3 0 R >>
+stream
+/DeviceRGB CS
+/DeviceRGB cs
+q
+/E1 gs
+1.000000 0.000000 -0.000000 1.000000 2.666016 3.203125 cm
+1.000000 1.000000 1.000000 scn
+5.528595 9.267629 m
+5.788945 9.527978 6.211055 9.527978 6.471404 9.267629 c
+10.471404 5.267628 l
+10.731753 5.007279 10.731753 4.585169 10.471404 4.324820 c
+6.471404 0.324820 l
+6.211055 0.064469 5.788945 0.064469 5.528595 0.324820 c
+5.268246 0.585169 5.268246 1.007278 5.528595 1.267628 c
+8.390524 4.129557 l
+0.666667 4.129557 l
+0.298477 4.129557 0.000000 4.428034 0.000000 4.796224 c
+0.000000 5.164413 0.298477 5.462891 0.666667 5.462891 c
+8.390524 5.462891 l
+5.528595 8.324820 l
+5.268246 8.585169 5.268246 9.007279 5.528595 9.267629 c
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  671
+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
+0000000074 00000 n
+0000000801 00000 n
+0000000823 00000 n
+0000000996 00000 n
+0000001070 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+1129
+%%EOF

+ 80 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/LeftSide/Search/KMImagenameBotaSearchInputPrefiex.imageset/prefix.pdf

@@ -0,0 +1,80 @@
+%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 2.666504 3.203125 cm
+0.250980 0.274510 0.325490 scn
+5.528595 9.267629 m
+5.788945 9.527978 6.211055 9.527978 6.471404 9.267629 c
+10.471404 5.267628 l
+10.731753 5.007279 10.731753 4.585169 10.471404 4.324820 c
+6.471404 0.324820 l
+6.211055 0.064469 5.788945 0.064469 5.528595 0.324820 c
+5.268246 0.585169 5.268246 1.007278 5.528595 1.267628 c
+8.390524 4.129557 l
+0.666667 4.129557 l
+0.298477 4.129557 0.000000 4.428034 0.000000 4.796224 c
+0.000000 5.164413 0.298477 5.462891 0.666667 5.462891 c
+8.390524 5.462891 l
+5.528595 8.324820 l
+5.268246 8.585169 5.268246 9.007279 5.528595 9.267629 c
+h
+f*
+n
+Q
+
+endstream
+endobj
+
+3 0 obj
+  664
+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
+0000000754 00000 n
+0000000776 00000 n
+0000000949 00000 n
+0000001023 00000 n
+trailer
+<< /ID [ (some) (id) ]
+   /Root 6 0 R
+   /Size 7
+>>
+startxref
+1082
+%%EOF

+ 275 - 48
PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/Search/KMBotaSearchViewController.swift

@@ -6,13 +6,29 @@
 //
 
 import Cocoa
+import KMComponentLibrary
 
-class KMBotaSearchViewController: NSViewController {
+extension KMNSearchKey.wholeWords {
+    static let botaSearch = "BotaSearchWholeWordsKey"
+}
+
+extension KMNSearchKey.caseSensitive {
+    static let botaSearch = "BotaSearchCaseSensitiveKey"
+}
+
+enum KMNBotaSearchType: Int {
+    case search = 1
+    case replace = 2
+}
+
+class KMBotaSearchViewController: KMNBotaBaseViewController {
     @IBOutlet weak var searchField: NSSearchField!
     @IBOutlet weak var segmentedControl: KMSegmentedControl!
     
     @IBOutlet weak var topView: NSBox!
     
+    @IBOutlet weak var topHeightConst: NSLayoutConstraint!
+    
     var contentView: NSView? {
         didSet {
             if let view = self.contentView {
@@ -35,6 +51,8 @@ class KMBotaSearchViewController: NSViewController {
     @IBOutlet var scrollView: NSScrollView!
     @IBOutlet weak var tableView: KMBotaTableView!
     
+    
+    
     private lazy var topContentView_: KMNBotaSearchTopView? = {
         let view = KMNBotaSearchTopView.createFromNib()
         return view
@@ -57,61 +75,96 @@ class KMBotaSearchViewController: NSViewController {
     override func loadView() {
         super.loadView()
         
-        if let data = topContentView_ {
-//            topView.contentView = topContentView_
-            topContentView_?.wantsLayer = true
-            topContentView_?.layer?.backgroundColor = NSColor.red.cgColor
+        topView.borderWidth = 0
+        topView.fillColor = .clear
+        topView.contentView = topContentView_
+        topContentView_?.itemClick = { [unowned self] idx, params in
+            if idx == KMNBotaSearchTopItemKey.search.rawValue {
+                if let data = params.first as? ComponentButton {
+                    showSearchGroupView(sender: data)
+                }
+            } else if idx == KMNBotaSearchTopItemKey.replace.rawValue {
+                if handdler.type == .search {
+                    handdler.type = .replace
+                    showReplaceView()
+                } else {
+                    handdler.type = .search
+                    showSearchView()
+                }
+            } else if idx == KMNBotaSearchTopItemKey.switch.rawValue {
+                
+            } else if idx == KMNBotaSearchTopItemKey.previous.rawValue {
+                tableViewMoveUp(tableView)
+            } else if idx == KMNBotaSearchTopItemKey.next.rawValue {
+                tableViewMoveDown(tableView)
+            }
+        }
+        
+        showSearchView()
+        topContentView_?.valueDidChange = { [unowned self] sender, info in
+            guard let string = info?[.newKey] as? String else {
+                return
+            }
+            
+            let isCase = KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch)
+            let isWholeWord = KMDataManager.ud_bool(forKey: KMNSearchKey.wholeWords.botaSearch)
+            handdler.search(keyword: string, isCase: isCase, isWholeWord: isWholeWord) { [unowned self] results in
+                searchResults = results ?? []
+                
+                showResult()
+                tableView.reloadData()
+            }
         }
         
         self.emptySearchLabel.stringValue = KMLocalizedString("No Results")
         self.emptySearchLabel.textColor = KMAppearance.Layout.h1Color()
         self.emptyBox.fillColor = KMAppearance.Layout.l0Color()
-        self.searchLabel.stringValue = KMLocalizedString("Search")
-        self.searchLabel.textColor = KMAppearance.Layout.h0Color()
-        self.searchTips.stringValue = KMLocalizedString("Search")
-        self.searchTips.textColor = KMAppearance.Layout.h2Color()
-        self.searchResultsLabel.textColor = KMAppearance.Layout.h1Color()
-        self.pageLabel.stringValue = KMLocalizedString("Page")
-        self.pageLabel.textColor = KMAppearance.Layout.h1Color()
-        self.searchResultsView.isHidden = true
+//        self.searchLabel.stringValue = KMLocalizedString("Search")
+//        self.searchLabel.textColor = KMAppearance.Layout.h0Color()
+//        self.searchTips.stringValue = KMLocalizedString("Search")
+//        self.searchTips.textColor = KMAppearance.Layout.h2Color()
+//        self.searchResultsLabel.textColor = KMAppearance.Layout.h1Color()
+//        self.pageLabel.stringValue = KMLocalizedString("Page")
+//        self.pageLabel.textColor = KMAppearance.Layout.h1Color()
+//        self.searchResultsView.isHidden = true
         
-        self.searchDomeButton.title = KMLocalizedString("Done")
-        self.searchDomeButton.toolTip = KMLocalizedString("Done")
-        self.searchDomeButton.setTitleColor(KMAppearance.Layout.w0Color())
-        self.searchDomeButton.wantsLayer = true
-        self.searchDomeButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
-        self.searchDomeButton.layer?.cornerRadius = 4.0
+//        self.searchDomeButton.title = KMLocalizedString("Done")
+//        self.searchDomeButton.toolTip = KMLocalizedString("Done")
+//        self.searchDomeButton.setTitleColor(KMAppearance.Layout.w0Color())
+//        self.searchDomeButton.wantsLayer = true
+//        self.searchDomeButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
+//        self.searchDomeButton.layer?.cornerRadius = 4.0
     //    self.searchDomeButton.hidden = YES;
         
-        self.searchField.wantsLayer = true
+//        self.searchField.wantsLayer = true
     //    self.searchField.layer.backgroundColor = [KMAppearance KMColor_Layout_L1].CGColor;
-        self.searchField.layer?.cornerRadius = 1.0
-        self.searchField.layer?.borderWidth = 1.0
-        self.searchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor
+//        self.searchField.layer?.cornerRadius = 1.0
+//        self.searchField.layer?.borderWidth = 1.0
+//        self.searchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor
         
-        self.searchBox.fillColor = KMAppearance.Interactive.s0Color()
+//        self.searchBox.fillColor = KMAppearance.Interactive.s0Color()
     //    self.searchField.hidden = YES;
-        self.searchBox.downCallback = { [unowned self] downEntered, box, _ in
-            if (downEntered) {
-                self.searchField.isHidden = false
-                self.searchDomeButton.isHidden = false
-                self.searchBox.isHidden = true
-                self.searchField.becomeFirstResponder()
-            }
-        }
+//        self.searchBox.downCallback = { [unowned self] downEntered, box, _ in
+//            if (downEntered) {
+//                self.searchField.isHidden = false
+//                self.searchDomeButton.isHidden = false
+//                self.searchBox.isHidden = true
+//                self.searchField.becomeFirstResponder()
+//            }
+//        }
         
-        self.searchBox.isHidden = true
+//        self.searchBox.isHidden = true
         
         contentView = tableView.enclosingScrollView
         
-        let menu = NSMenu()
-        _ = menu.addItem(title: KMLocalizedString("Whole Words Only"), action: #selector(toggleWholeWordSearch), target: self)
-        _ = menu.addItem(title: KMLocalizedString("Ignore Case"), action: #selector(toggleCaseInsensitiveSearch), target: self)
-        (self.searchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menu
-        (self.searchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search PDF")
-        
-        self.searchField.target = self
-        self.searchField.action = #selector(searchAction)
+//        let menu = NSMenu()
+//        _ = menu.addItem(title: KMLocalizedString("Whole Words Only"), action: #selector(toggleWholeWordSearch), target: self)
+//        _ = menu.addItem(title: KMLocalizedString("Ignore Case"), action: #selector(toggleCaseInsensitiveSearch), target: self)
+//        (self.searchField.cell as? NSSearchFieldCell)?.searchMenuTemplate = menu
+//        (self.searchField.cell as? NSSearchFieldCell)?.placeholderString = KMLocalizedString("Search PDF")
+//
+//        self.searchField.target = self
+//        self.searchField.action = #selector(searchAction)
     }
     
     override func viewDidLoad() {
@@ -125,24 +178,112 @@ class KMBotaSearchViewController: NSViewController {
 //        self.mwcFlags.wholeWordSearch = KMDataManager.ud_integer(forKey: SKWholeWordSearchKey)
 //        self.mwcFlags.caseInsensitiveSearch = KMDataManager.ud_integer(forKey: SKCaseInsensitiveSearchKey)
         
-        self.tableView.backgroundColor = KMAppearance.Layout.l0Color()
+//        self.tableView.backgroundColor = KMAppearance.Layout.l0Color()
         self.tableView.tableColumn(withIdentifier: kPageColumnId)?.headerCell.title = KMLocalizedString("Page")
     }
     
     override func viewDidAppear() {
         super.viewDidAppear()
         
-        self.searchField.becomeFirstResponder()
+//        self.searchField.becomeFirstResponder()
         self.updateViewColor()
         DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged), name: NSApplication.interfaceThemeChangedNotification, object: nil)
     }
     
+    override func updateUILanguage() {
+        super.updateUILanguage()
+        
+        KMMainThreadExecute {
+            self.topContentView_?.resultLabel.stringValue = KMLocalizedString("Result:") + " " + "\(self.handdler.searchResults.count)"
+        }
+    }
+    
+    override func updateUIThemeColor() {
+        super.updateUIThemeColor()
+        
+        KMMainThreadExecute {
+            self.view.wantsLayer = true
+            let color = KMNColorTools.colorBg_layoutMiddle()
+            self.view.layer?.backgroundColor = color.cgColor
+            
+            self.tableView.backgroundColor = color
+            
+            self.topContentView_?.resultLabel.textColor = KMNColorTools.colorText_3()
+        }
+    }
+    
     func updateViewColor() {
         if (KMAppearance.isDarkMode()) {
-            self.searchField.layer?.backgroundColor = NSColor(red: 57.0/255.0, green: 60.0/255.0, blue: 62.0/255.0, alpha: 1).cgColor
+//            self.searchField.layer?.backgroundColor = NSColor(red: 57.0/255.0, green: 60.0/255.0, blue: 62.0/255.0, alpha: 1).cgColor
         } else {
-            self.searchField.layer?.backgroundColor = .white
+//            self.searchField.layer?.backgroundColor = .white
+        }
+    }
+    
+    func showSearchView() {
+        topContentView_?.showSearch()
+        
+        topHeightConst.constant = topContentView_?.fetchContentHeight(type: handdler.type, hasResult: handdler.searchResults.isEmpty == false) ?? 0
+    }
+    
+    func showReplaceView() {
+        topContentView_?.showReplace()
+         
+        topHeightConst.constant = topContentView_?.fetchContentHeight(type: handdler.type, hasResult: handdler.searchResults.isEmpty == false) ?? 0
+    }
+    
+    func showResult() {
+        topContentView_?.showResult(type: handdler.type)
+        
+        topContentView_?.resultLabel.stringValue = KMLocalizedString("Result:") + " " + "\(self.handdler.searchResults.count)"
+        topHeightConst.constant = topContentView_?.fetchContentHeight(type: handdler.type, hasResult: searchResults.isEmpty == false) ?? 0
+    }
+    
+    // MARK: - Group View
+    
+    func showSearchGroupView(sender: ComponentButton) {
+        var viewHeight: CGFloat = 8
+        var menuItemArr: [ComponentMenuitemProperty] = []
+        let titles = ["Search", "Find and Replace", "", "Whole Words", "Case Sensitive"]
+        for i in titles {
+            if i.isEmpty {
+                let menuI = ComponentMenuitemProperty.divider()
+                menuItemArr.append(menuI)
+                viewHeight += 8
+            } else {
+                let menuI = ComponentMenuitemProperty(text: KMLocalizedString(i))
+                menuItemArr.append(menuI)
+                viewHeight += 36
+            }
+        }
+        
+        if handdler.type == .search {
+            menuItemArr.first?.righticon = NSImage(named: "KMNImageNameMenuSelect")
+        } else if handdler.type == .replace {
+            let info = menuItemArr.safe_element(for: 1) as? ComponentMenuitemProperty
+            info?.righticon = NSImage(named: "KMNImageNameMenuSelect")
+        }
+        if let info = menuItemArr.safe_element(for: 3) as? ComponentMenuitemProperty {
+            if KMDataManager.ud_bool(forKey: KMNSearchKey.wholeWords.botaSearch) {
+                info.righticon = NSImage(named: "KMNImageNameMenuSelect")
+            }
+        }
+        if let info = menuItemArr.last {
+            if KMDataManager.ud_bool(forKey: KMNSearchKey.caseSensitive.botaSearch) {
+                info.righticon = NSImage(named: "KMNImageNameMenuSelect")
+            }
         }
+        
+        let groupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
+        searchGroupView = groupView
+        groupView?.groupDelegate = self
+        groupView?.frame = CGRectMake(310, 0, 200, viewHeight)
+        groupView?.updateGroupInfo(menuItemArr)
+        
+        var point = sender.convert(sender.frame.origin, to: nil)
+        point.y -= viewHeight
+        groupView?.showWithPoint(point, relativeTo: sender)
+        searchGroupTarget = sender
     }
     
     @objc func themeChanged(_ notification: NSNotification) {
@@ -205,11 +346,11 @@ class KMBotaSearchViewController: NSViewController {
     func updataLeftSideFindView() {
         if (self.searchResults.count > 0) {
             self.emptyBox.isHidden = true
-            self.searchResultsView.isHidden = false
-            self.searchResultsLabel.stringValue = String(format: KMLocalizedString("%ld Results"), self.searchResults.count)
+//            self.searchResultsView.isHidden = false
+//            self.searchResultsLabel.stringValue = String(format: KMLocalizedString("%ld Results"), self.searchResults.count)
         } else {
             self.emptyBox.isHidden = false
-            self.searchResultsView.isHidden = true
+//            self.searchResultsView.isHidden = true
         }
     }
 }
@@ -328,3 +469,89 @@ extension KMBotaSearchViewController: KMBotaTableViewDelegate {
     }
     
 }
+
+//MARK: - ComponentGroupDelegate
+
+extension KMBotaSearchViewController: ComponentGroupDelegate {
+    func componentGroupDidDismiss(group: ComponentGroup?) {
+//        if group == groupView_ {
+//            removeGroupView()
+//        } else if group == menuGroupView_ {
+//            group?.removeFromSuperview()
+//            menuGroupView_ = nil
+//        } else
+        if group == searchGroupView {
+//            searchGroupView_ = nil
+            searchGroupTarget?.properties.state = .normal
+            searchGroupTarget?.reloadData()
+            searchGroupTarget = nil
+        }
+    }
+    
+    func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
+//        if group == groupView_ {
+//            if let selItem = menuItemProperty {
+//                let index = group?.menuItemArr.firstIndex(of: selItem)
+//                if index == 0 {
+//                    expandAllComments(item: NSMenuItem())
+//                } else if index == 1 {
+//                    collapseAllComments(item: NSMenuItem())
+//                } else if index == 2 {
+//                    removeAllOutlineItem(item: NSMenuItem())
+//                }
+//            }
+//        } else if group == menuGroupView_ {
+//            if let selItem = menuItemProperty {
+//                let index = group?.menuItemArr.firstIndex(of: selItem)
+//                if index == 0 {
+//                    addItemAction()
+//                } else if index == 1 {
+//                    addChildItemAction()
+//                } else if index == 2 {
+//                    addHigherItemAction()
+//                } else if index == 4 {
+//                    deleteItemAction()
+//                } else if index == 6 {
+//                    group?.removeFromSuperview()
+//
+//                    editItemAction()
+//                } else if index == 7 {
+//                    renameItemAction()
+//                } else if index == 8 {
+//                    changeItemAction()
+//                } else if index == 10 {
+//                    promoteItemAction()
+//                } else if index == 11 {
+//                    demoteItemAction()
+//                }
+//
+//                group?.removeFromSuperview()
+//            }
+//        } else
+        if group == searchGroupView {
+            guard let menuI = menuItemProperty else {
+                return
+            }
+            let idx = group?.menuItemArr.firstIndex(of: menuI)
+            if idx == 0 { // search
+                
+            } else if idx == 1 { // replace
+                
+            } else if idx == 3 {
+                let key = KMNSearchKey.wholeWords.botaSearch
+                let value = KMDataManager.ud_bool(forKey: key)
+                KMDataManager.ud_set(!value, forKey: key)
+                
+//                BOTAOutlineView.wholeWords = !value
+            } else if idx == 4 {
+                let key = KMNSearchKey.caseSensitive.botaSearch
+                let value = KMDataManager.ud_bool(forKey: key)
+                KMDataManager.ud_set(!value, forKey: key)
+                
+//                BOTAOutlineView.caseSensitive = !value
+            }
+        }
+    }
+}
+
+

+ 12 - 145
PDF Office/PDF Master/Class/PDFWindowController/Side/LeftSide/Search/KMBotaSearchViewController.xib

@@ -11,17 +11,9 @@
                 <outlet property="box" destination="jTx-lq-IMO" id="3np-QT-RBm"/>
                 <outlet property="emptyBox" destination="YP3-hM-jIu" id="76W-OU-rpD"/>
                 <outlet property="emptySearchLabel" destination="RZV-VM-ubG" id="P1g-lE-xp0"/>
-                <outlet property="pageLabel" destination="DG6-KM-fPE" id="WCW-t2-N6y"/>
                 <outlet property="scrollView" destination="uYq-U5-IA0" id="42p-Xm-ruW"/>
-                <outlet property="searchBox" destination="m5j-WZ-WP4" id="cvH-DW-gmp"/>
-                <outlet property="searchDomeButton" destination="Sot-lU-418" id="nTG-J5-bHW"/>
-                <outlet property="searchField" destination="Exf-lV-10v" id="HAb-dG-HXv"/>
-                <outlet property="searchLabel" destination="ZGS-QS-aFB" id="Uq1-gi-5tY"/>
-                <outlet property="searchResultsLabel" destination="avX-Sl-7dw" id="U6D-o9-NG9"/>
-                <outlet property="searchResultsView" destination="hP4-NA-Ala" id="srK-Ds-q65"/>
-                <outlet property="searchTips" destination="LV8-kC-pPy" id="vhL-vd-TBZ"/>
-                <outlet property="segmentedControl" destination="2OM-I5-WuT" id="hoB-xe-Aav"/>
                 <outlet property="tableView" destination="QYw-8e-Jnj" id="TGk-gM-Ff7"/>
+                <outlet property="topHeightConst" destination="0b0-lw-Bus" id="hBi-Pw-Olu"/>
                 <outlet property="topView" destination="N6c-s0-ocg" id="K55-rt-wdv"/>
                 <outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
             </connections>
@@ -32,30 +24,22 @@
             <rect key="frame" x="0.0" y="0.0" width="240" height="513"/>
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <subviews>
-                <searchField wantsLayer="YES" verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Exf-lV-10v">
-                    <rect key="frame" x="16" y="452" width="164" height="20"/>
-                    <searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="border" usesSingleLineMode="YES" id="So1-aF-t1m">
-                        <font key="font" metaFont="system"/>
-                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
-                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
-                    </searchFieldCell>
-                </searchField>
                 <box boxType="custom" borderType="none" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="jTx-lq-IMO">
-                    <rect key="frame" x="0.0" y="0.0" width="240" height="422"/>
+                    <rect key="frame" x="0.0" y="0.0" width="240" height="433"/>
                     <view key="contentView" id="Hlh-Hl-xR6">
-                        <rect key="frame" x="0.0" y="0.0" width="240" height="422"/>
+                        <rect key="frame" x="0.0" y="0.0" width="240" height="433"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                     </view>
                     <color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
                 </box>
                 <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="YP3-hM-jIu">
-                    <rect key="frame" x="0.0" y="0.0" width="240" height="422"/>
+                    <rect key="frame" x="0.0" y="0.0" width="240" height="433"/>
                     <view key="contentView" id="fz0-9N-dbN">
-                        <rect key="frame" x="0.0" y="0.0" width="240" height="422"/>
+                        <rect key="frame" x="0.0" y="0.0" width="240" height="433"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
                             <customView translatesAutoresizingMaskIntoConstraints="NO" id="Vwh-uE-n99">
-                                <rect key="frame" x="-5" y="125" width="250" height="173"/>
+                                <rect key="frame" x="-5" y="130" width="250" height="173"/>
                                 <subviews>
                                     <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="fCc-bq-sMR">
                                         <rect key="frame" x="55" y="33" width="140" height="140"/>
@@ -96,143 +80,27 @@
                     <color key="borderColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
                     <color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
                 </box>
-                <customView translatesAutoresizingMaskIntoConstraints="NO" id="2OM-I5-WuT" customClass="KMSegmentedControl" customModule="PDF_Reader_Pro" customModuleProvider="target">
-                    <rect key="frame" x="184" y="480" width="50" height="25"/>
-                    <constraints>
-                        <constraint firstAttribute="width" constant="50" id="4nF-ia-dJx"/>
-                        <constraint firstAttribute="height" constant="25" id="LzF-7O-4Fm"/>
-                    </constraints>
-                </customView>
-                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ZGS-QS-aFB">
-                    <rect key="frame" x="14" y="484" width="40" height="17"/>
-                    <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="Eil-0G-5lp">
-                        <font key="font" metaFont="system" size="14"/>
-                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
-                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
-                    </textFieldCell>
-                </textField>
-                <box boxType="custom" borderWidth="0.0" cornerRadius="1" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="m5j-WZ-WP4" customClass="KMBox" customModule="PDF_Reader_Pro" customModuleProvider="target">
-                    <rect key="frame" x="16" y="452" width="208" height="20"/>
-                    <view key="contentView" id="zoj-cx-Qv1">
-                        <rect key="frame" x="0.0" y="0.0" width="208" height="20"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <customView translatesAutoresizingMaskIntoConstraints="NO" id="AuZ-iT-8Sc">
-                                <rect key="frame" x="79" y="0.0" width="50" height="20"/>
-                                <subviews>
-                                    <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="F6A-U5-mv7">
-                                        <rect key="frame" x="0.0" y="2" width="16" height="16"/>
-                                        <constraints>
-                                            <constraint firstAttribute="height" constant="16" id="Cq1-jy-gdR"/>
-                                            <constraint firstAttribute="width" constant="16" id="akO-nn-kuV"/>
-                                        </constraints>
-                                        <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="KMImageNameUXIconBtnSearchbarSearch" id="3va-Z6-CLg"/>
-                                    </imageView>
-                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="LV8-kC-pPy">
-                                        <rect key="frame" x="15" y="2" width="37" height="16"/>
-                                        <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="8F8-Ba-XlP">
-                                            <font key="font" metaFont="system"/>
-                                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
-                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
-                                        </textFieldCell>
-                                    </textField>
-                                </subviews>
-                                <constraints>
-                                    <constraint firstItem="LV8-kC-pPy" firstAttribute="leading" secondItem="F6A-U5-mv7" secondAttribute="trailing" constant="1" id="ONS-wa-eK6"/>
-                                    <constraint firstAttribute="trailing" secondItem="LV8-kC-pPy" secondAttribute="trailing" id="Y6y-4l-exs"/>
-                                    <constraint firstItem="F6A-U5-mv7" firstAttribute="leading" secondItem="AuZ-iT-8Sc" secondAttribute="leading" id="hwu-Jp-he1"/>
-                                    <constraint firstItem="F6A-U5-mv7" firstAttribute="centerY" secondItem="AuZ-iT-8Sc" secondAttribute="centerY" id="oRV-Me-PUb"/>
-                                    <constraint firstItem="LV8-kC-pPy" firstAttribute="centerY" secondItem="AuZ-iT-8Sc" secondAttribute="centerY" id="vZX-iJ-SG0"/>
-                                </constraints>
-                            </customView>
-                        </subviews>
-                        <constraints>
-                            <constraint firstItem="AuZ-iT-8Sc" firstAttribute="top" secondItem="zoj-cx-Qv1" secondAttribute="top" id="52i-Ye-JVI"/>
-                            <constraint firstAttribute="bottom" secondItem="AuZ-iT-8Sc" secondAttribute="bottom" id="5Ui-6N-ba1"/>
-                        </constraints>
-                    </view>
-                    <constraints>
-                        <constraint firstItem="AuZ-iT-8Sc" firstAttribute="centerX" secondItem="m5j-WZ-WP4" secondAttribute="centerX" id="PPE-UO-t8C"/>
-                    </constraints>
-                </box>
-                <customView translatesAutoresizingMaskIntoConstraints="NO" id="hP4-NA-Ala">
-                    <rect key="frame" x="16" y="430" width="208" height="14"/>
-                    <subviews>
-                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="avX-Sl-7dw">
-                            <rect key="frame" x="-2" y="0.0" width="33" height="14"/>
-                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="aJC-Hn-dib">
-                                <font key="font" metaFont="smallSystem"/>
-                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
-                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
-                            </textFieldCell>
-                        </textField>
-                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="DG6-KM-fPE">
-                            <rect key="frame" x="177" y="0.0" width="33" height="14"/>
-                            <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="kMU-mK-L5o">
-                                <font key="font" metaFont="smallSystem"/>
-                                <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
-                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
-                            </textFieldCell>
-                        </textField>
-                    </subviews>
-                    <constraints>
-                        <constraint firstItem="avX-Sl-7dw" firstAttribute="leading" secondItem="hP4-NA-Ala" secondAttribute="leading" id="CNl-c5-s1P"/>
-                        <constraint firstItem="DG6-KM-fPE" firstAttribute="centerY" secondItem="avX-Sl-7dw" secondAttribute="centerY" id="XAZ-BC-Zau"/>
-                        <constraint firstAttribute="bottom" secondItem="avX-Sl-7dw" secondAttribute="bottom" id="bKj-K9-CUH"/>
-                        <constraint firstItem="avX-Sl-7dw" firstAttribute="top" secondItem="hP4-NA-Ala" secondAttribute="top" id="f4d-IP-x9i"/>
-                        <constraint firstAttribute="trailing" secondItem="DG6-KM-fPE" secondAttribute="trailing" id="uCD-1a-2mT"/>
-                    </constraints>
-                </customView>
-                <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Sot-lU-418">
-                    <rect key="frame" x="188" y="452" width="36" height="20"/>
-                    <constraints>
-                        <constraint firstAttribute="height" constant="20" id="bAq-jA-d1x"/>
-                        <constraint firstAttribute="width" constant="36" id="nWW-zz-pQ3"/>
-                    </constraints>
-                    <buttonCell key="cell" type="square" title="Button" bezelStyle="shadowlessSquare" alignment="center" imageScaling="proportionallyDown" inset="2" id="ueG-bM-doV">
-                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
-                        <font key="font" metaFont="cellTitle"/>
-                    </buttonCell>
-                    <connections>
-                        <action selector="searchDomeButtonAtion:" target="-2" id="6wa-gN-8qu"/>
-                    </connections>
-                </button>
                 <box boxType="custom" cornerRadius="4" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="N6c-s0-ocg">
-                    <rect key="frame" x="0.0" y="422" width="240" height="91"/>
+                    <rect key="frame" x="0.0" y="433" width="240" height="80"/>
                     <view key="contentView" id="Rh3-0t-oum">
-                        <rect key="frame" x="1" y="1" width="238" height="89"/>
+                        <rect key="frame" x="1" y="1" width="238" height="78"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                     </view>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="80" id="0b0-lw-Bus"/>
+                    </constraints>
                 </box>
             </subviews>
             <constraints>
-                <constraint firstItem="hP4-NA-Ala" firstAttribute="top" secondItem="Exf-lV-10v" secondAttribute="bottom" constant="8" id="1Kg-bg-LGr"/>
-                <constraint firstItem="hP4-NA-Ala" firstAttribute="trailing" secondItem="m5j-WZ-WP4" secondAttribute="trailing" id="4if-ph-rEL"/>
-                <constraint firstItem="Exf-lV-10v" firstAttribute="top" secondItem="2OM-I5-WuT" secondAttribute="bottom" constant="8" id="Gpq-6K-sPq"/>
                 <constraint firstItem="YP3-hM-jIu" firstAttribute="centerX" secondItem="jTx-lq-IMO" secondAttribute="centerX" id="I0r-BH-fx2"/>
                 <constraint firstAttribute="trailing" secondItem="jTx-lq-IMO" secondAttribute="trailing" id="OKR-iq-2Yo"/>
-                <constraint firstItem="Sot-lU-418" firstAttribute="leading" secondItem="Exf-lV-10v" secondAttribute="trailing" constant="8" id="PHH-tq-U24"/>
-                <constraint firstAttribute="trailing" secondItem="m5j-WZ-WP4" secondAttribute="trailing" constant="16" id="RpE-ng-ElP"/>
-                <constraint firstItem="ZGS-QS-aFB" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="16" id="SOD-0k-NPp"/>
                 <constraint firstItem="YP3-hM-jIu" firstAttribute="height" secondItem="jTx-lq-IMO" secondAttribute="height" id="Swr-lv-cAz"/>
                 <constraint firstItem="N6c-s0-ocg" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" id="TY9-6v-k6I"/>
-                <constraint firstItem="m5j-WZ-WP4" firstAttribute="leading" secondItem="Exf-lV-10v" secondAttribute="leading" id="Vnk-Pc-Nhr"/>
-                <constraint firstItem="hP4-NA-Ala" firstAttribute="leading" secondItem="m5j-WZ-WP4" secondAttribute="leading" id="Wgl-cP-RDF"/>
-                <constraint firstItem="m5j-WZ-WP4" firstAttribute="top" secondItem="Exf-lV-10v" secondAttribute="top" id="Wm2-5T-Veu"/>
-                <constraint firstAttribute="trailing" secondItem="Sot-lU-418" secondAttribute="trailing" constant="16" id="XMf-el-u9F"/>
-                <constraint firstItem="2OM-I5-WuT" firstAttribute="centerY" secondItem="ZGS-QS-aFB" secondAttribute="centerY" id="Z3A-Y9-HK5"/>
-                <constraint firstItem="2OM-I5-WuT" firstAttribute="top" secondItem="Hz6-mo-xeY" secondAttribute="top" constant="8" id="d8L-Cb-uC8"/>
                 <constraint firstItem="jTx-lq-IMO" firstAttribute="top" secondItem="N6c-s0-ocg" secondAttribute="bottom" id="fxI-PG-yX7"/>
                 <constraint firstItem="YP3-hM-jIu" firstAttribute="width" secondItem="jTx-lq-IMO" secondAttribute="width" id="g2b-zR-cbj"/>
-                <constraint firstItem="Sot-lU-418" firstAttribute="centerY" secondItem="Exf-lV-10v" secondAttribute="centerY" id="gac-i5-Jlm"/>
-                <constraint firstItem="m5j-WZ-WP4" firstAttribute="top" secondItem="2OM-I5-WuT" secondAttribute="bottom" constant="8" id="gbI-es-zpr"/>
-                <constraint firstAttribute="trailing" secondItem="2OM-I5-WuT" secondAttribute="trailing" constant="6" id="o9z-IY-CCJ"/>
-                <constraint firstItem="jTx-lq-IMO" firstAttribute="top" secondItem="hP4-NA-Ala" secondAttribute="bottom" constant="8" id="oi4-Ow-iIw"/>
                 <constraint firstItem="N6c-s0-ocg" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="pW1-kZ-XbL"/>
-                <constraint firstItem="Exf-lV-10v" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" constant="16" id="qE5-qt-cCi"/>
                 <constraint firstAttribute="trailing" secondItem="N6c-s0-ocg" secondAttribute="trailing" id="qHN-gL-kQr"/>
                 <constraint firstItem="jTx-lq-IMO" firstAttribute="leading" secondItem="Hz6-mo-xeY" secondAttribute="leading" id="ski-kz-g2S"/>
-                <constraint firstItem="m5j-WZ-WP4" firstAttribute="bottom" secondItem="Exf-lV-10v" secondAttribute="bottom" id="slj-io-4Ku"/>
                 <constraint firstItem="YP3-hM-jIu" firstAttribute="centerY" secondItem="jTx-lq-IMO" secondAttribute="centerY" id="vqG-Le-4nc"/>
                 <constraint firstAttribute="bottom" secondItem="jTx-lq-IMO" secondAttribute="bottom" id="yHi-h2-Tme"/>
             </constraints>
@@ -244,7 +112,7 @@
             <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
             <clipView key="contentView" drawsBackground="NO" id="7P5-FJ-Eig">
                 <rect key="frame" x="0.0" y="0.0" width="204" height="400"/>
-                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                <autoresizingMask key="autoresizingMask"/>
                 <subviews>
                     <tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="firstColumnOnly" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" rowHeight="40" viewBased="YES" id="QYw-8e-Jnj" customClass="KMBotaTableView" customModule="PDF_Reader_Pro" customModuleProvider="target">
                         <rect key="frame" x="0.0" y="0.0" width="204" height="400"/>
@@ -342,6 +210,5 @@
     </objects>
     <resources>
         <image name="KMImageNameEmptySearch" width="140" height="140"/>
-        <image name="KMImageNameUXIconBtnSearchbarSearch" width="16" height="16"/>
     </resources>
 </document>

+ 2 - 0
PDF Office/PDF Master/KMClass/Left/Search/Tools/KMNSearchHanddler.swift

@@ -11,6 +11,8 @@ class KMNSearchHanddler: NSObject {
     
     weak var pdfView: CPDFView?
     
+    var type: KMNBotaSearchType = .search
+    
     var searchResults: [KMSearchMode] = []
     
     func search(keyword: String, isCase: Bool, isWholeWord: Bool, callback: @escaping (([KMSearchMode]?) -> Void)) {

+ 162 - 5
PDF Office/PDF Master/KMClass/Left/Search/View/KMNBotaSearchTopView.swift

@@ -8,6 +8,14 @@
 import Cocoa
 import KMComponentLibrary
 
+enum KMNBotaSearchTopItemKey: Int {
+    case search = 1
+    case replace = 2
+    case `switch` = 3
+    case previous = 4
+    case next = 5
+}
+
 class KMNBotaSearchTopView: NSView, NibLoadable {
     
     @IBOutlet weak var topBox: NSBox!
@@ -16,24 +24,73 @@ class KMNBotaSearchTopView: NSView, NibLoadable {
     
     @IBOutlet weak var centerHeightConst: NSLayoutConstraint!
     
+    var itemClick: KMCommonClickBlock?
+    var valueDidChange: KMValueDidChangeBlock?
+    
+    private var topHeight_: CGFloat = 40
+    private var centerHeight_ : CGFloat = 72
+    private var bottomHeight_: CGFloat = 32
+    private var vSpace_: CGFloat = 8
+    
     private lazy var searchButton_: ComponentButton = {
         let view = ComponentButton()
         view.properties = ComponentButtonProperty(type: .text_gray, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearch"))
+        view.setTarget(self, action: #selector(searchAction))
+        return view
+    }()
+    
+    private lazy var searchInput_: NSTextField = {
+        let view = NSTextField()
+        view.placeholderString = KMLocalizedString("Search (⌥⌘F)")
+        view.delegate = self
+        return view
+    }()
+    
+    private lazy var replaceButton_: ComponentButton = {
+        let view = ComponentButton()
+        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchReplace"))
+        view.setTarget(self, action: #selector(replaceAction))
+        return view
+    }()
+    
+    private lazy var switchButton_: ComponentButton = {
+        let view = ComponentButton()
+        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchSwitch"))
+        view.setTarget(self, action: #selector(switchAction))
         return view
     }()
     
-    private lazy var input_: ComponentInput = {
-        let view = ComponentInput()
-        view.properties = ComponentInputProperty(size: .s, placeholder: KMLocalizedString("Search"), text: "")
+    private lazy var centerView_: KMNSearchReplaceItemView = {
+        let view = KMNSearchReplaceItemView()
         return view
     }()
     
-    private lazy var closeButton_: ComponentButton = {
+    private lazy var resultLabel_: NSTextField = {
+        let view = NSTextField(labelWithString: "")
+        view.font = ComponentLibrary.shared.getFontFromKey("mac/body-xs-medium")
+        return view
+    }()
+    
+    private lazy var previousButton_: ComponentButton = {
+        let view = ComponentButton()
+        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchPreviousDisable"))
+        view.setTarget(self, action: #selector(previousAction))
+        return view
+    }()
+    
+    private lazy var nextButton_: ComponentButton = {
         let view = ComponentButton()
-        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaClose"))
+        view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchNext"))
+        view.setTarget(self, action: #selector(nextActon))
         return view
     }()
     
+    var resultLabel: NSTextField {
+        get {
+            return resultLabel_
+        }
+    }
+    
     override func draw(_ dirtyRect: NSRect) {
         super.draw(dirtyRect)
 
@@ -47,9 +104,109 @@ class KMNBotaSearchTopView: NSView, NibLoadable {
     }
     
     func initSubviews() {
+        topBox.borderWidth = 0
         topBox.contentView?.addSubview(searchButton_)
         searchButton_.km_add_leading_constraint(constant: 12)
         searchButton_.km_add_size_constraint(size: NSSize(width: 16, height: 16))
         searchButton_.km_add_centerY_constraint()
+        
+        topBox.contentView?.addSubview(searchInput_)
+        searchInput_.km_add_leading_constraint(equalTo: searchButton_, attribute: .trailing, constant: 8)
+        searchInput_.km_add_centerY_constraint()
+        searchInput_.km_add_height_constraint(constant: 20)
+        searchInput_.km_add_trailing_constraint(constant: -76)
+        
+        topBox.contentView?.addSubview(switchButton_)
+        switchButton_.km_add_trailing_constraint(constant: -12)
+        switchButton_.km_add_centerY_constraint()
+        switchButton_.km_add_size_constraint(size: NSSize(width: 24, height: 24))
+        
+        topBox.contentView?.addSubview(replaceButton_)
+        replaceButton_.km_add_trailing_constraint(equalTo: switchButton_, attribute: .leading, constant: -8)
+        replaceButton_.km_add_centerY_constraint()
+        replaceButton_.km_add_size_constraint(size: NSSize(width: 24, height: 24))
+        
+        centerBox.isHidden = true
+        centerBox.borderWidth = 0
+        centerBox.contentView = centerView_
+        
+        bottomBox.isHidden = true
+        bottomBox.borderWidth = 0
+        bottomBox.contentView?.addSubview(resultLabel_)
+        resultLabel_.km_add_top_constraint(constant: 16)
+        resultLabel_.km_add_leading_constraint(constant: 16)
+        
+        bottomBox.contentView?.addSubview(nextButton_)
+        nextButton_.km_add_trailing_constraint(constant: -16)
+        nextButton_.km_add_top_constraint(constant: 16)
+        nextButton_.km_add_size_constraint(size: .init(width: 16, height: 16))
+        
+        bottomBox.contentView?.addSubview(previousButton_)
+        previousButton_.km_add_trailing_constraint(equalTo: nextButton_, attribute: .leading, constant: -8)
+        previousButton_.km_add_top_constraint(constant: 16)
+        previousButton_.km_add_size_constraint(size: .init(width: 16, height: 16))
+        
+    }
+    
+    func showSearch() {
+        centerBox.isHidden = true
+        
+        centerHeightConst.constant = 0
+    }
+    
+    func showReplace() {
+        centerBox.isHidden = false
+        
+        centerHeightConst.constant = centerHeight_
+    }
+    
+    func showResult(type: KMNBotaSearchType) {
+        bottomBox.isHidden = false
+    }
+    
+    func hideResult(type: KMNBotaSearchType) {
+        bottomBox.isHidden = true
+    }
+    
+    func fetchContentHeight(type: KMNBotaSearchType, hasResult: Bool) -> CGFloat {
+        var height: CGFloat = topHeight_
+        if type == .search {
+            
+        } else if type == .replace {
+            height += centerHeight_
+        }
+        
+        height += (hasResult ? bottomHeight_+vSpace_ : 0)
+        return height
+    }
+    
+    // MARK: - Actions
+    
+    @objc func searchAction() {
+        itemClick?(KMNBotaSearchTopItemKey.search.rawValue, searchButton_)
+    }
+    
+    @objc func replaceAction() {
+        itemClick?(KMNBotaSearchTopItemKey.replace.rawValue)
+    }
+    
+    @objc func switchAction() {
+        itemClick?(KMNBotaSearchTopItemKey.switch.rawValue)
+    }
+    
+    @objc func previousAction() {
+        itemClick?(KMNBotaSearchTopItemKey.previous.rawValue)
+    }
+    
+    @objc func nextActon() {
+        itemClick?(KMNBotaSearchTopItemKey.next.rawValue)
+    }
+}
+
+extension KMNBotaSearchTopView: NSTextFieldDelegate {
+    func controlTextDidChange(_ obj: Notification) {
+        if searchInput_.isEqual(to: obj.object) {
+            valueDidChange?(searchInput_, [.newKey : searchInput_.stringValue])
+        }
     }
 }

+ 83 - 0
PDF Office/PDF Master/KMClass/Left/Search/View/KMNSearchReplaceItemView.swift

@@ -0,0 +1,83 @@
+//
+//  KMNSearchReplaceItemView.swift
+//  PDF Reader Pro
+//
+//  Created by User-Tangchao on 2024/12/2.
+//
+
+import Cocoa
+import KMComponentLibrary
+
+class KMNSearchReplaceItemView: NSView {
+    private lazy var input_: ComponentInput = {
+        let view = ComponentInput()
+        let prop = ComponentInputProperty()
+        prop.size = .s
+        prop.showPrefix = true
+        prop.placeholder = KMLocalizedString("Replace with...")
+//        KMImagenameBotaSearchInputPrefiex
+        view.properties = prop
+        return view
+    }()
+    
+    private lazy var replaceAllButton_: ComponentButton = {
+        let view = ComponentButton()
+        let prop = ComponentButtonProperty()
+        prop.type = .default_tertiary
+        prop.size = .xxs
+        prop.buttonText = KMLocalizedString("Replace All")
+        view.properties = prop
+        return view
+    }()
+    
+    private lazy var replaceButton_: ComponentButton = {
+        let view = ComponentButton()
+        let prop = ComponentButtonProperty()
+        prop.type = .primary
+        prop.size = .xxs
+        prop.buttonText = KMLocalizedString("Replace")
+        view.properties = prop
+        return view
+    }()
+    
+    
+    convenience init() {
+        self.init(frame: .init(x: 0, y: 0, width: 300, height: 60))
+        
+        initSubviews()
+    }
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+        initSubviews()
+    }
+    
+    func initSubviews() {
+        addSubview(input_)
+        addSubview(replaceAllButton_)
+        addSubview(replaceButton_)
+        
+        input_.km_add_leading_constraint(constant: 12)
+        input_.km_add_top_constraint(constant: 8)
+        input_.km_add_trailing_constraint(constant: -12)
+        input_.km_add_height_constraint(constant: 32)
+        
+        replaceButton_.km_add_height_constraint(constant: 24)
+        replaceButton_.km_add_trailing_constraint(constant: -12)
+        replaceButton_.km_add_bottom_constraint()
+        replaceButton_.km_add_width_constraint(constant: replaceButton_.properties.propertyInfo.viewWidth)
+        
+        replaceAllButton_.km_add_height_constraint(constant: 24)
+        replaceAllButton_.km_add_trailing_constraint(equalTo: replaceButton_, attribute: .leading, constant: -8)
+        replaceAllButton_.km_add_bottom_constraint()
+        replaceAllButton_.km_add_width_constraint(constant: replaceAllButton_.properties.propertyInfo.viewWidth)
+    }
+
+    override func draw(_ dirtyRect: NSRect) {
+        super.draw(dirtyRect)
+
+        // Drawing code here.
+    }
+    
+}

+ 4 - 0
PDF Office/PDF Master/KMClass/Tools/Tool/KMNColorTools.swift

@@ -19,6 +19,10 @@ class KMNColorTools: NSObject {
         return ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
     }
     
+    @inline (__always) class func colorText_3() -> NSColor {
+        return ComponentLibrary.shared.getComponentColorFromKey("colorText/3")
+    }
+    
     @inline (__always) class func colorPrimary_textLight() -> NSColor {
         return ComponentLibrary.shared.getComponentColorFromKey("colorPrimary/textLight")
     }

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

@@ -311,6 +311,9 @@
 		65B143AD2CF06B97001B5A69 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65B143942CF06B97001B5A69 /* String+KMExtensions.swift */; };
 		65B143AE2CF06B97001B5A69 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65B143942CF06B97001B5A69 /* String+KMExtensions.swift */; };
 		65B143AF2CF06B97001B5A69 /* String+KMExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65B143942CF06B97001B5A69 /* String+KMExtensions.swift */; };
+		65C404312CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C404302CFDA62500B32BDC /* KMNSearchReplaceItemView.swift */; };
+		65C404322CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C404302CFDA62500B32BDC /* KMNSearchReplaceItemView.swift */; };
+		65C404332CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65C404302CFDA62500B32BDC /* KMNSearchReplaceItemView.swift */; };
 		65C9CAEA2CA16232009794E5 /* libpaddle2onnx.1.0.7.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 65C9CAE62CA16231009794E5 /* libpaddle2onnx.1.0.7.dylib */; };
 		65C9CAEB2CA16232009794E5 /* libpaddle2onnx.1.0.7.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 65C9CAE62CA16231009794E5 /* libpaddle2onnx.1.0.7.dylib */; };
 		65C9CAEC2CA16232009794E5 /* libpaddle2onnx.1.0.7.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 65C9CAE62CA16231009794E5 /* libpaddle2onnx.1.0.7.dylib */; };
@@ -5661,6 +5664,7 @@
 		65B143922CF06B97001B5A69 /* Array+KMExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Array+KMExtensions.swift"; sourceTree = "<group>"; };
 		65B143932CF06B97001B5A69 /* NSColor+KMExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSColor+KMExtensions.swift"; sourceTree = "<group>"; };
 		65B143942CF06B97001B5A69 /* String+KMExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+KMExtensions.swift"; sourceTree = "<group>"; };
+		65C404302CFDA62500B32BDC /* KMNSearchReplaceItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMNSearchReplaceItemView.swift; sourceTree = "<group>"; };
 		65C9CAE62CA16231009794E5 /* libpaddle2onnx.1.0.7.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libpaddle2onnx.1.0.7.dylib; sourceTree = "<group>"; };
 		65C9CAE72CA16232009794E5 /* ComDocumentAIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ComDocumentAIKit.framework; sourceTree = "<group>"; };
 		65C9CAE82CA16232009794E5 /* libDocumentAI.3.3.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libDocumentAI.3.3.3.dylib; sourceTree = "<group>"; };
@@ -8269,6 +8273,7 @@
 			children = (
 				65F9F4892CFCABD100F187A8 /* KMNBotaSearchTopView.swift */,
 				65F9F48D2CFCABE700F187A8 /* KMNBotaSearchTopView.xib */,
+				65C404302CFDA62500B32BDC /* KMNSearchReplaceItemView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -16720,6 +16725,7 @@
 				AD867FB329DFBB2700F00440 /* KMAnnotationOutlineSectionView.swift in Sources */,
 				9FDD0F6F294AD13C000C4DAD /* KMMainViewController+Action.swift in Sources */,
 				BB67EE1D2B54FFEF00573BF0 /* ASIFormDataRequest.m in Sources */,
+				65C404312CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */,
 				9F69DBB22B512614003D4C45 /* KMAnnotationTextWidgetOptionsViewController.swift in Sources */,
 				BB79E7192CE617CB0052CAD5 /* KMEditImageController.swift in Sources */,
 				ADDF839B2B391A5D00A81A4E /* PDFCertExportAccessoryView.swift in Sources */,
@@ -18601,6 +18607,7 @@
 				BB451A7B2CF59EBC003E1565 /* KMHighlightController.swift in Sources */,
 				653647C32CDCA5DE00CDB13E /* KMBatchOperateLeftViewController.swift in Sources */,
 				9FCFEC9D2AD152FA00EAD2CB /* CustomAlertView.swift in Sources */,
+				65C404322CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */,
 				BB42A5D92B8F0F840092C524 /* KMTabbingHintWindowController.swift in Sources */,
 				BB67EE1B2B54FFEF00573BF0 /* ASIHTTPRequest.m in Sources */,
 				BB031B7C2C47BB090099F7AD /* KMUserFbListHeaderItemView.swift in Sources */,
@@ -19179,6 +19186,7 @@
 				BB6BA4C62B0B4A0F00462CAE /* KMLeftSideEmptyFileViewController.swift in Sources */,
 				BBB9B32D299A5D6D004F3235 /* GTMOAuth2KeychainCompatibility.m in Sources */,
 				BB6719E72AD28527003D44D5 /* CPDFLineAnnotation+PDFListView.swift in Sources */,
+				65C404332CFDA62500B32BDC /* KMNSearchReplaceItemView.swift in Sources */,
 				9F0CB4EB2986559400007028 /* KMDesignToken+PaddingBottom.swift in Sources */,
 				BBD1F78D296FACA300343885 /* KMPageEditExtractSettingView.swift in Sources */,
 				BB88E456294045B4002B3655 /* KMPDFConvertManager.swift in Sources */,