Meke sure update progress indicator on the main thread

This commit is contained in:
1024jp 2018-04-30 13:30:13 +09:00
parent 40af6aa310
commit e5b801e708
4 changed files with 44 additions and 35 deletions

View File

@ -5,6 +5,11 @@ Change Log
unreleased
--------------------------
### Improvements
- Optimize syntax highlighting performance.
### Fixes
- Fix an issue where the sidebar inspector did close inward when the pane was switched after opening the sidebar outward.

View File

@ -1,12 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11129.15" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14109" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11129.15"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14109"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ProgressViewController" customModule="CotEditor" customModuleProvider="target">
<connections>
<outlet property="button" destination="8F8-Xs-904" id="V2l-0o-Mce"/>
<outlet property="descriptionField" destination="6wC-fK-qvF" id="55I-Re-Chx"/>
<outlet property="indicator" destination="YTj-ob-Ly1" id="IP9-8t-jFp"/>
<outlet property="view" destination="Gmd-ZI-UeZ" id="nU1-c1-xf9"/>
</connections>
</customObject>
@ -17,7 +21,6 @@
<progressIndicator verticalHuggingPriority="750" maxValue="1" bezeled="NO" indeterminate="YES" controlSize="small" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="YTj-ob-Ly1">
<rect key="frame" x="20" y="49" width="380" height="12"/>
<connections>
<binding destination="-2" name="value" keyPath="progress.completedUnitCount" previousBinding="v6v-x5-gdD" id="b1i-dQ-Y0z"/>
<binding destination="-2" name="isIndeterminate" keyPath="progress.indeterminate" id="zNb-ZJ-Fct"/>
<binding destination="-2" name="maxValue" keyPath="progress.totalUnitCount" id="v6v-x5-gdD"/>
</connections>
@ -40,9 +43,6 @@
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="-2" name="value" keyPath="progress.localizedDescription" id="g6V-Oh-8kN"/>
</connections>
</textField>
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="8F8-Xs-904">
<rect key="frame" x="288" y="13" width="118" height="32"/>

View File

@ -44,7 +44,11 @@ final class ProgressViewController: NSViewController {
@objc private dynamic let message: String
private var progressObserver: NSKeyValueObservation?
private var descriptionObserver: NSKeyValueObservation?
private var finishObserver: NSKeyValueObservation?
@IBOutlet private weak var indicator: NSProgressIndicator?
@IBOutlet private weak var descriptionField: NSTextField?
@IBOutlet private weak var button: NSButton?
@ -59,12 +63,28 @@ final class ProgressViewController: NSViewController {
super.init(nibName: nil, bundle: nil)
self.progressObserver = progress.observe(\.isFinished) { [weak self] (progress, _) in
self.progressObserver = progress.observe(\.completedUnitCount, options: .initial) { [weak self] (progress, _) in
guard progress.completedUnitCount % 100 == 0 else { return }
DispatchQueue.main.async {
self?.indicator?.doubleValue = Double(progress.completedUnitCount)
}
}
self.descriptionObserver = progress.observe(\.localizedDescription, options: .initial) { [weak self] (progress, _) in
DispatchQueue.main.async {
self?.descriptionField?.stringValue = progress.localizedDescription
}
}
self.finishObserver = progress.observe(\.isFinished) { [weak self] (progress, _) in
guard closesWhenFinished, progress.isFinished else { return }
DispatchQueue.main.async {
self?.dismiss(nil)
}
}
}
required init?(coder: NSCoder) {
@ -75,6 +95,8 @@ final class ProgressViewController: NSViewController {
deinit {
self.progressObserver?.invalidate()
self.descriptionObserver?.invalidate()
self.finishObserver?.invalidate()
}

View File

@ -59,7 +59,7 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
var string: String?
var parseRange: NSRange = .notFound
let progress: Progress
let progress: Progress // can be updated from a background thread
var highlightBlock: (([SyntaxType: [NSRange]]) -> Void)?
@ -117,15 +117,11 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
guard !self.isCancelled else { return }
DispatchQueue.main.async { [weak progress = self.progress] in
progress?.localizedDescription = NSLocalizedString("Applying colors to text", comment: "")
}
self.progress.localizedDescription = NSLocalizedString("Applying colors to text", comment: "")
self.highlightBlock?(results)
DispatchQueue.main.async { [weak progress = self.progress] in
progress?.completedUnitCount += 1
}
self.progress.completedUnitCount += 1
}
@ -228,9 +224,7 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
guard let extractors = self.extractors[syntaxType] else { continue }
// update indicator sheet message
DispatchQueue.main.async { [weak progress = self.progress] in
progress?.localizedDescription = String(format: NSLocalizedString("Extracting %@…", comment: ""), syntaxType.localizedName)
}
self.progress.localizedDescription = String(format: NSLocalizedString("Extracting %@…", comment: ""), syntaxType.localizedName)
let childProgress = Progress(totalUnitCount: Int64(extractors.count), parent: self.progress, pendingUnitCount: 1)
@ -241,17 +235,13 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
guard !self.isCancelled else { return }
let extractedRanges = extractors[index].ranges(in: self.string!, range: self.parseRange)
if !extractedRanges.isEmpty {
rangesQueue.sync {
ranges += extractedRanges
}
}
// progress indicator
DispatchQueue.main.async { [weak childProgress] in
childProgress?.completedUnitCount += 1
}
childProgress.completedUnitCount += 1
}
guard !self.isCancelled else { return [:] }
@ -259,20 +249,14 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
// store range array
highlights[syntaxType] = ranges
// progress indicator
DispatchQueue.main.async { [weak childProgress] in
guard let childProgress = childProgress else { return }
childProgress.completedUnitCount = childProgress.totalUnitCount
}
}
guard !self.isCancelled else { return [:] }
// comments and quoted text
DispatchQueue.main.async { [weak progress = self.progress] in
progress?.localizedDescription = String(format: NSLocalizedString("Extracting %@…", comment: ""),
self.progress.localizedDescription = String(format: NSLocalizedString("Extracting %@…", comment: ""),
NSLocalizedString("comments and quoted texts", comment: ""))
}
let commentAndQuoteRanges = self.extractCommentsWithQuotes()
for (key, value) in commentAndQuoteRanges {
highlights[key, default: []].append(contentsOf: value)
@ -282,9 +266,7 @@ final class SyntaxHighlightParseOperation: AsynchronousOperation, ProgressReport
let sanitized = sanitize(highlights: highlights)
DispatchQueue.main.async { [weak progress = self.progress] in
progress?.completedUnitCount += 1
}
self.progress.completedUnitCount += 1
return sanitized
}