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