From d68a613057d097a8c6a3bdeabbf9ab9b2e646994 Mon Sep 17 00:00:00 2001 From: Marc DENTY Date: Mon, 25 Sep 2017 16:47:46 +0200 Subject: [PATCH] migration to swift4 --- .../project.pbxproj | 55 +++++-- Tesseract-Box-Editor/Box.swift | 2 +- .../BoxResizeDelegateProtocol.swift | 2 +- Tesseract-Box-Editor/CharacterView.swift | 40 +++-- Tesseract-Box-Editor/Document.swift | 42 ++--- .../DocumentWindowController.swift | 148 ++++++++++-------- Tesseract-Box-Editor/ImageView.swift | 6 +- .../ImageViewWithSelectionRect.swift | 98 ++++++------ 8 files changed, 229 insertions(+), 164 deletions(-) diff --git a/Tesseract-Box-Editor.xcodeproj/project.pbxproj b/Tesseract-Box-Editor.xcodeproj/project.pbxproj index 5e0efba..2b5a103 100644 --- a/Tesseract-Box-Editor.xcodeproj/project.pbxproj +++ b/Tesseract-Box-Editor.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ B39693C11942A0F5004E13AA /* ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B39693C01942A0F5004E13AA /* ImageView.swift */; }; B3C9261219340283006A1020 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B3C9261119340283006A1020 /* Cocoa.framework */; }; B3C9261C19340283006A1020 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B3C9261A19340283006A1020 /* InfoPlist.strings */; }; - B3C9261E19340283006A1020 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B3C9261D19340283006A1020 /* main.m */; }; B3C9262219340283006A1020 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = B3C9262019340283006A1020 /* Credits.rtf */; }; B3C9262519340283006A1020 /* TBEAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B3C9262419340283006A1020 /* TBEAppDelegate.m */; }; B3C9262819340283006A1020 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = B3C9262619340283006A1020 /* MainMenu.xib */; }; @@ -27,6 +26,7 @@ B3C9263A19340283006A1020 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B3C9263819340283006A1020 /* InfoPlist.strings */; }; B3C9263C19340283006A1020 /* Tesseract_Box_EditorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B3C9263B19340283006A1020 /* Tesseract_Box_EditorTests.m */; }; B3DB7F61195E131E00ACE379 /* BoxResizeDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DB7F60195E131E00ACE379 /* BoxResizeDelegateProtocol.swift */; }; + FBDE49971F794DAC00298A64 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE49961F794D8C00298A64 /* main.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -58,7 +58,6 @@ B3C9261619340283006A1020 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; B3C9261919340283006A1020 /* Tesseract-Box-Editor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tesseract-Box-Editor-Info.plist"; sourceTree = ""; }; B3C9261B19340283006A1020 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - B3C9261D19340283006A1020 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; B3C9261F19340283006A1020 /* Tesseract-Box-Editor-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tesseract-Box-Editor-Prefix.pch"; sourceTree = ""; }; B3C9262119340283006A1020 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; B3C9262319340283006A1020 /* TBEAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TBEAppDelegate.h; sourceTree = ""; }; @@ -73,6 +72,7 @@ B3DB7F60195E131E00ACE379 /* BoxResizeDelegateProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxResizeDelegateProtocol.swift; sourceTree = ""; }; B3EB961219634EAD00AD4EF9 /* TBE-1-thumb.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "TBE-1-thumb.jpg"; sourceTree = ""; }; B3EB961319634EAD00AD4EF9 /* TBE-1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "TBE-1.jpg"; sourceTree = ""; }; + FBDE49961F794D8C00298A64 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -162,11 +162,11 @@ B3C9261819340283006A1020 /* Supporting Files */ = { isa = PBXGroup; children = ( + FBDE49961F794D8C00298A64 /* main.m */, B3EB961219634EAD00AD4EF9 /* TBE-1-thumb.jpg */, B3EB961319634EAD00AD4EF9 /* TBE-1.jpg */, B3C9261919340283006A1020 /* Tesseract-Box-Editor-Info.plist */, B3C9261A19340283006A1020 /* InfoPlist.strings */, - B3C9261D19340283006A1020 /* main.m */, B3C9261F19340283006A1020 /* Tesseract-Box-Editor-Prefix.pch */, B3C9262019340283006A1020 /* Credits.rtf */, ); @@ -237,10 +237,14 @@ attributes = { CLASSPREFIX = TBE; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Erik Larsen"; TargetAttributes = { + B3C9260D19340283006A1020 = { + LastSwiftMigration = 0900; + }; B3C9262E19340283006A1020 = { + LastSwiftMigration = 0830; TestTargetID = B3C9260D19340283006A1020; }; }; @@ -292,6 +296,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + FBDE49971F794DAC00298A64 /* main.m in Sources */, B3DB7F61195E131E00ACE379 /* BoxResizeDelegateProtocol.swift in Sources */, B3839F36195DE74C00C45821 /* Document.swift in Sources */, B39693C11942A0F5004E13AA /* ImageView.swift in Sources */, @@ -301,7 +306,6 @@ B34AF637193FDCB400DA19FA /* CharacterView.swift in Sources */, B39693BD19424052004E13AA /* Box.swift in Sources */, B3C9262519340283006A1020 /* TBEAppDelegate.m in Sources */, - B3C9261E19340283006A1020 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -367,19 +371,30 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -396,6 +411,7 @@ ONLY_ACTIVE_ARCH = YES; PRODUCT_MODULE_NAME = TesseractBoxEditor; SDKROOT = macosx; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -407,19 +423,30 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -429,6 +456,8 @@ MACOSX_DEPLOYMENT_TARGET = 10.9; PRODUCT_MODULE_NAME = TesseractBoxEditor; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -447,6 +476,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Tesseract-Box-Editor/Tesseract Box Editor-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; WRAPPER_EXTENSION = app; }; name = Debug; @@ -465,6 +496,8 @@ PRODUCT_MODULE_NAME = TesseractBoxEditor; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Tesseract-Box-Editor/Tesseract Box Editor-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; WRAPPER_EXTENSION = app; }; name = Release; @@ -472,7 +505,8 @@ B3C9264319340283006A1020 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Tesseract-Box-Editor.app/Contents/MacOS/Tesseract-Box-Editor"; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", @@ -487,7 +521,8 @@ INFOPLIST_FILE = "Tesseract-Box-EditorTests/Tesseract-Box-EditorTests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "com.enlarsen.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tesseract Box Editor.app/Contents/MacOS/Tesseract Box Editor"; WRAPPER_EXTENSION = xctest; }; name = Debug; @@ -495,7 +530,8 @@ B3C9264419340283006A1020 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Tesseract-Box-Editor.app/Contents/MacOS/Tesseract-Box-Editor"; + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", @@ -506,7 +542,8 @@ INFOPLIST_FILE = "Tesseract-Box-EditorTests/Tesseract-Box-EditorTests-Info.plist"; PRODUCT_BUNDLE_IDENTIFIER = "com.enlarsen.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Tesseract Box Editor.app/Contents/MacOS/Tesseract Box Editor"; WRAPPER_EXTENSION = xctest; }; name = Release; diff --git a/Tesseract-Box-Editor/Box.swift b/Tesseract-Box-Editor/Box.swift index b57a418..6a4bad1 100644 --- a/Tesseract-Box-Editor/Box.swift +++ b/Tesseract-Box-Editor/Box.swift @@ -60,7 +60,7 @@ class Box: NSObject } } - class func boxToNSRect(box: Box) -> NSRect + class func boxToNSRect(_ box: Box) -> NSRect { return NSRect(x: box.x, y: box.y, width: box.width, height: box.height) } diff --git a/Tesseract-Box-Editor/BoxResizeDelegateProtocol.swift b/Tesseract-Box-Editor/BoxResizeDelegateProtocol.swift index 5e4ac48..7bf3762 100644 --- a/Tesseract-Box-Editor/BoxResizeDelegateProtocol.swift +++ b/Tesseract-Box-Editor/BoxResizeDelegateProtocol.swift @@ -10,7 +10,7 @@ import Foundation protocol BoxResizeDelegate { - func boxDidResize(rect: NSRect) + func boxDidResize(_ rect: NSRect) func doneDragging() func beganDragging() } diff --git a/Tesseract-Box-Editor/CharacterView.swift b/Tesseract-Box-Editor/CharacterView.swift index a6fdacb..0781123 100644 --- a/Tesseract-Box-Editor/CharacterView.swift +++ b/Tesseract-Box-Editor/CharacterView.swift @@ -40,8 +40,8 @@ class CharacterView: ImageViewWithSelectionRect override init(frame frameRect: NSRect) { super.init(frame: frameRect) - strokeColor = NSColor.grayColor().CGColor - fillColor = NSColor.clearColor().CGColor + strokeColor = NSColor.gray.cgColor + fillColor = NSColor.clear.cgColor lineDashPattern = [1, 1] duration = 10.0 } @@ -52,20 +52,18 @@ class CharacterView: ImageViewWithSelectionRect override func awakeFromNib() { - imageScaling = .ScaleProportionallyUpOrDown + imageScaling = .scaleProportionallyUpOrDown drawSelectionHandles = true } - func propagateValue(id: AnyObject, binding:NSString) + func propagateValue(_ id: AnyObject, binding:NSString) { - if let bindingInfo = self.infoForBinding(binding as String) + if let bindingInfo = self.infoForBinding(NSBindingName(rawValue: binding as String)) { - if let bindingOptions : AnyObject = bindingInfo[NSOptionsKey] - { - let transformer: NSValueTransformer = bindingOptions[NSValueTransformerBindingOption] as! NSValueTransformer - } + let bindingOptions: AnyObject = bindingInfo[NSBindingInfoKey.options] as AnyObject + let _: ValueTransformer = bindingOptions[NSBindingOption.valueTransformer] as! ValueTransformer } else { @@ -74,7 +72,7 @@ class CharacterView: ImageViewWithSelectionRect } - func updateCharacter(image: NSImage, cropPoint: NSPoint, rect: NSRect) + func updateCharacter(_ image: NSImage, cropPoint: NSPoint, rect: NSRect) { self.image = image @@ -93,14 +91,14 @@ class CharacterView: ImageViewWithSelectionRect } - override func mouseDown(theEvent: NSEvent) + override func mouseDown(with theEvent: NSEvent) { - let point = convertPoint(theEvent.locationInWindow, fromView: nil) - var transform = CGAffineTransformInvert(CATransform3DGetAffineTransform(selectionLayer.transform)) + let point = convert(theEvent.locationInWindow, from: nil) + let transform = CATransform3DGetAffineTransform(selectionLayer.transform).inverted() - for var i = 0; i < selectionHandleLayers.count; i++ + for i in 0 ..< selectionHandleLayers.count { - if CGPathContainsPoint(selectionHandleLayers[i].path, &transform, point, false) + if selectionHandleLayers[i].path?.contains(point, using: .winding, transform: transform) ?? false { self.startPointIndex = i break @@ -115,7 +113,7 @@ class CharacterView: ImageViewWithSelectionRect // TODO: also check whether the click was within the selection rectangle in prep for a move } - override func mouseUp(theEvent: NSEvent) + override func mouseUp(with theEvent: NSEvent) { startPointIndex = -1 @@ -125,11 +123,11 @@ class CharacterView: ImageViewWithSelectionRect } } - override func mouseDragged(theEvent: NSEvent) + override func mouseDragged(with theEvent: NSEvent) { - var point = convertPoint(theEvent.locationInWindow, fromView: nil) - let transform = CGAffineTransformInvert(CATransform3DGetAffineTransform(selectionLayer.transform)) - point = CGPointApplyAffineTransform(point, transform) + var point = convert(theEvent.locationInWindow, from: nil) + let transform = CATransform3DGetAffineTransform(selectionLayer.transform).inverted() + point = point.applying(transform) let newRect = computeResizedSelectionRectangle(self.startPointIndex, dragPoint: point) // NSLog("newRect: \(newRect)") @@ -145,4 +143,4 @@ class CharacterView: ImageViewWithSelectionRect } -} \ No newline at end of file +} diff --git a/Tesseract-Box-Editor/Document.swift b/Tesseract-Box-Editor/Document.swift index 70ce9b9..9883dd6 100644 --- a/Tesseract-Box-Editor/Document.swift +++ b/Tesseract-Box-Editor/Document.swift @@ -36,20 +36,20 @@ class Document: NSDocument var pageIndex = Dictionary() - override var windowNibName: String + override var windowNibName: NSNib.Name? { - return "Document" + return NSNib.Name(rawValue: "Document") } // TODO: This needs vastly improved error handling and value checking - func readBoxFile(path: String) + func readBoxFile(_ path: String) { var error: NSError? = nil var boxes: [Box] = [] let fileText: NSString? do { - fileText = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding) - } catch var error1 as NSError { + fileText = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue) + } catch let error1 as NSError { error = error1 fileText = nil } @@ -59,23 +59,23 @@ class Document: NSDocument NSLog("Error: \(mError.localizedDescription)") } - fileText!.enumerateLinesUsingBlock({line, stop in + fileText!.enumerateLines({line, stop in let box = Box() - var intValue: CInt = 0 +// var intValue: CInt = 0 var characterAsString: NSString? - let scanner = NSScanner(string: line) + let scanner = Scanner(string: line) scanner.caseSensitive = true scanner.charactersToBeSkipped = nil - scanner.scanUpToString(" ", intoString: &characterAsString) + scanner.scanUpTo(" ", into: &characterAsString) if let character = characterAsString { box.character = character as String } - scanner.charactersToBeSkipped = NSCharacterSet.whitespaceCharacterSet() + scanner.charactersToBeSkipped = CharacterSet.whitespaces box.x = self.getNextIntValue(scanner) box.y = self.getNextIntValue(scanner) @@ -89,20 +89,20 @@ class Document: NSDocument } - func getNextIntValue(scanner: NSScanner) -> Int + func getNextIntValue(_ scanner: Scanner) -> Int { var intValue: CInt = 0 - scanner.scanInt(&intValue) + scanner.scanInt32(&intValue) return Int(intValue) } func createPageIndex() { - pageIndex.removeAll(keepCapacity: true) + pageIndex.removeAll(keepingCapacity: true) var current = -1 - for var i = 0; i < boxes.count; i++ + for i in 0 ..< boxes.count { if current != boxes[i].page { @@ -113,24 +113,24 @@ class Document: NSDocument } - override func readFromURL(url: NSURL, ofType typeName: String) throws + override func read(from url: URL, ofType typeName: String) throws { - readBoxFile(url.path!) + readBoxFile(url.path) } - override func writeToURL(url: NSURL, ofType typeName: String) throws + override func write(to url: URL, ofType typeName: String) throws { var outError: NSError! = NSError(domain: "Migrator", code: 0, userInfo: nil) var output = "" for box in boxes { - output = output.stringByAppendingString(box.formatForWriting()) + output = output + box.formatForWriting() } do { - try output.writeToFile(url.path!, atomically: true, encoding: NSUTF8StringEncoding) - } catch var error as NSError { + try output.write(toFile: url.path, atomically: true, encoding: String.Encoding.utf8) + } catch let error as NSError { outError = error } @@ -148,7 +148,7 @@ class Document: NSDocument override func makeWindowControllers() { - let windowController = DocumentWindowController(windowNibName: self.windowNibName) + let windowController = DocumentWindowController(windowNibName: NSNib.Name(rawValue: self.windowNibName!.rawValue)) addWindowController(windowController) } diff --git a/Tesseract-Box-Editor/DocumentWindowController.swift b/Tesseract-Box-Editor/DocumentWindowController.swift index f8c88c4..81356ed 100644 --- a/Tesseract-Box-Editor/DocumentWindowController.swift +++ b/Tesseract-Box-Editor/DocumentWindowController.swift @@ -28,6 +28,30 @@ import Cocoa import QuartzCore +// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. +// Consider refactoring the code to use the non-optional operators. +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} + +// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. +// Consider refactoring the code to use the non-optional operators. +fileprivate func > (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l > r + default: + return rhs < lhs + } +} + class DocumentWindowController: NSWindowController, BoxResizeDelegate { @@ -36,9 +60,9 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate @IBOutlet var tableArrayController: NSArrayController! @IBOutlet var tableView: NSTableView! - override var windowNibName: String + override var windowNibName: NSNib.Name? { - return "Document" + return NSNib.Name(rawValue: "Document") } var currentDocument: Document @@ -72,13 +96,13 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate { willSet { - self.willChangeValueForKey("isThereAPreviousPage") - self.willChangeValueForKey("isThereANextPage") + self.willChangeValue(forKey: "isThereAPreviousPage") + self.willChangeValue(forKey: "isThereANextPage") } didSet { - self.didChangeValueForKey("isThereAPreviousPage") - self.didChangeValueForKey("isThereANextPage") + self.didChangeValue(forKey: "isThereAPreviousPage") + self.didChangeValue(forKey: "isThereANextPage") } } @@ -113,7 +137,7 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - override class func automaticallyNotifiesObserversForKey(key: String) -> Bool + override class func automaticallyNotifiesObservers(forKey key: String) -> Bool { if key == "isThereAPreviousPage" || key == "isThereANextPage" @@ -130,11 +154,11 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate override func awakeFromNib() { - mainImageView.imageScaling = .ScaleProportionallyUpOrDown + mainImageView.imageScaling = .scaleProportionallyUpOrDown characterView.delegate = self } - override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [NSObject : AnyObject]?, context: UnsafeMutablePointer) + func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [String : Any]?, context: UnsafeMutableRawPointer?) { if tableArrayController.selectedObjects.count > 0 { @@ -178,31 +202,31 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate // Someday do everything as straight up bindings. // Problems with direct binding: need image and crop as well as the box down in the CharacterView, // unless I move the image down to the viewer classes and then let them crop the image. - func resizeBox(rect: NSRect, index: Int) + @objc func resizeBox(_ rect: NSRect, index: Int) { let box = boxes[index] box.x = Int(rect.origin.x) box.y = Int(rect.origin.y) box.width = Int(rect.size.width) box.height = Int(rect.size.height) - if self.window!.undoManager!.undoing && index == tableArrayController.selectionIndex + if self.window!.undoManager!.isUndoing && index == tableArrayController.selectionIndex { updateSelectedCharacterDisplays() } } - func changeCharacter(char: String, index: Int) + @objc func changeCharacter(_ char: String, index: Int) { let box = boxes[index] - self.window!.undoManager!.prepareWithInvocationTarget(self).changeCharacter(box.character, index: index) - if !self.window!.undoManager!.undoing + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).changeCharacter(box.character, index: index) + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Change \"\(box.character)\" to \"\(char)\"") } box.character = char } - func boxDidResize(rect: NSRect) + func boxDidResize(_ rect: NSRect) { let selectionIndex = tableArrayController.selectionIndex resizeBox(rect, index: selectionIndex) @@ -214,8 +238,8 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate let selectionIndex = tableArrayController.selectionIndex let currentRect = box.boxToNSRect() - self.window!.undoManager!.prepareWithInvocationTarget(self).resizeBox(currentRect, index: selectionIndex) - if !self.window!.undoManager!.undoing + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).resizeBox(currentRect, index: selectionIndex) + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Resize Box") } @@ -227,31 +251,31 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate updateSelectedCharacterDisplays() } - func insertBox(box: Box, index: Int) + @objc func insertBox(_ box: Box, index: Int) { - self.window!.undoManager!.prepareWithInvocationTarget(self).removeBox(index) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).removeBox(index) - if !self.window!.undoManager!.undoing + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Insert Box") } - boxes.insert(box, atIndex: index) + boxes.insert(box, at: index) } - func removeBox(index: Int) + @objc func removeBox(_ index: Int) { let box = boxes[index] - self.window!.undoManager!.prepareWithInvocationTarget(self).insertBox(box, index: index) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).insertBox(box, index: index) - if !self.window!.undoManager!.undoing + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Delete Box") } - boxes.removeAtIndex(index) + boxes.remove(at: index) } - func mergeBoxes(index: Int) + func mergeBoxes(_ index: Int) { let firstBox = boxes[index] @@ -260,10 +284,10 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate let secondBox = boxes[index + 1] self.window!.undoManager!.beginUndoGrouping() - self.window!.undoManager!.prepareWithInvocationTarget(self).insertBox(secondBox, index: index + 1) - self.window!.undoManager!.prepareWithInvocationTarget(self).resizeBox(firstBox.boxToNSRect(), index: index) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).insertBox(secondBox, index: index + 1) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).resizeBox(firstBox.boxToNSRect(), index: index) - if !self.window!.undoManager!.undoing + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Merge Boxes") } @@ -283,16 +307,16 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - func splitBoxes(index: Int) + func splitBoxes(_ index: Int) { let box = boxes[index] self.window!.undoManager!.beginUndoGrouping() - self.window!.undoManager!.prepareWithInvocationTarget(self).removeBox(index + 1) - self.window!.undoManager!.prepareWithInvocationTarget(self).resizeBox(box.boxToNSRect(), index:index) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).removeBox(index + 1) + (self.window!.undoManager!.prepare(withInvocationTarget: self) as AnyObject).resizeBox(box.boxToNSRect(), index:index) - if !self.window!.undoManager!.undoing + if !self.window!.undoManager!.isUndoing { self.window!.undoManager!.setActionName("Split Box") } @@ -307,30 +331,30 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate newBox.x2 = box.x2 box.x2 = newBox.x - 2 - boxes.insert(newBox, atIndex: index + 1) + boxes.insert(newBox, at: index + 1) currentDocument.createPageIndex() updateSelectedCharacterDisplays() } - @IBAction func mergeToolbarItem(sender: NSToolbarItem) + @IBAction func mergeToolbarItem(_ sender: NSToolbarItem) { mergeBoxes(tableArrayController.selectionIndex) } - @IBAction func splitToolbarItem(sender: NSToolbarItem) + @IBAction func splitToolbarItem(_ sender: NSToolbarItem) { splitBoxes(tableArrayController.selectionIndex) } - func deleteToolbarItem(sender: NSToolbarItem) + func deleteToolbarItem(_ sender: NSToolbarItem) { removeBox(tableArrayController.selectionIndex) } - func insertToolbarItem(sender: NSToolbarItem) + func insertToolbarItem(_ sender: NSToolbarItem) { let index = tableArrayController.selectionIndex @@ -348,7 +372,7 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } // The KVO will see the change in selection and update the image view - @IBAction func previousPage(sender: NSButton) + @IBAction func previousPage(_ sender: NSButton) { let index = currentTiffPage - 1 if index < 0 @@ -363,7 +387,7 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - @IBAction func nextPage(sender: NSButton) + @IBAction func nextPage(_ sender: NSButton) { let index = currentTiffPage + 1 if index >= boxes.count @@ -377,9 +401,9 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - func scanRow(y: Int, width:Int, pointer: UnsafePointer) -> Bool + func scanRow(_ y: Int, width:Int, pointer: UnsafePointer) -> Bool { - for var x = 0; x < width; x++ + for x in 0 ..< width { if pointer[(x + y * width) * 4] != 0xff // only check red, could cause trouble { @@ -389,9 +413,9 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate return false } - func scanColumn(x: Int, height: Int, width: Int, pointer: UnsafePointer) -> Bool + func scanColumn(_ x: Int, height: Int, width: Int, pointer: UnsafePointer) -> Bool { - for var y = 0; y < height; y++ + for y in 0 ..< height { if pointer[(x + y * width) * 4] != 0xff // only check red { @@ -401,7 +425,7 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate return false } - func updateCharacterView(box: Box) + func updateCharacterView(_ box: Box) { if box.page < pagesFromImage.count { @@ -412,13 +436,13 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate croppedImage.lockFocus() NSGraphicsContext.saveGraphicsState() - NSGraphicsContext.currentContext()?.imageInterpolation = NSImageInterpolation.None - NSGraphicsContext.currentContext()?.shouldAntialias = false + NSGraphicsContext.current?.imageInterpolation = NSImageInterpolation.none + NSGraphicsContext.current?.shouldAntialias = false - image.drawInRect(NSRect(x: 0, y: 0, width: box.width + 10, height: box.height + 10), - fromRect: NSRect(x: box.x - 5, y: box.y - 5, + image.draw(in: NSRect(x: 0, y: 0, width: box.width + 10, height: box.height + 10), + from: NSRect(x: box.x - 5, y: box.y - 5, width: box.width + 10, height: box.height + 10), - operation: NSCompositingOperation.CompositeCopy, + operation: .copy, fraction: 1.0) NSGraphicsContext.restoreGraphicsState() @@ -429,7 +453,7 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - func windowDidResize(notification: NSNotification!) + func windowDidResize(_ notification: Notification!) { if mainImageView.image != nil { @@ -447,9 +471,9 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate observing = false } - if let tiffUrl = currentDocument.fileURL?.URLByDeletingPathExtension!.URLByAppendingPathExtension("tif") + if let tiffUrl = currentDocument.fileURL?.deletingPathExtension().appendingPathExtension("tif") { - let imageFromFile = NSImage(byReferencingURL: tiffUrl) + let imageFromFile = NSImage(byReferencing: tiffUrl) pagesFromImage = imageFromFile.representations as! [NSBitmapImageRep] mainImageView.trimImage(imageFromFile) currentTiffPage = 0 @@ -467,14 +491,14 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate // TODO: Need to allow composed characters // TODO: Investigate the method for interpreting characters, see orange book - override func keyDown(theEvent: NSEvent) + override func keyDown(with theEvent: NSEvent) { self.interpretKeyEvents([theEvent]) } // function for interpretKeyEvents - override func insertText(insertString: AnyObject) + override func insertText(_ insertString: Any) { if let characters = insertString as? String { @@ -484,21 +508,21 @@ class DocumentWindowController: NSWindowController, BoxResizeDelegate } - override func encodeRestorableStateWithCoder(coder: NSCoder) + override func encodeRestorableState(with coder: NSCoder) { - super.encodeRestorableStateWithCoder(coder) - coder.encodeInteger(tableArrayController.selectionIndex, forKey: "selectionIndex") + super.encodeRestorableState(with: coder) + coder.encode(tableArrayController.selectionIndex, forKey: "selectionIndex") } - override func restoreStateWithCoder(coder: NSCoder) + override func restoreState(with coder: NSCoder) { - super.restoreStateWithCoder(coder) - let index = coder.decodeIntegerForKey("selectionIndex") + super.restoreState(with: coder) + let index = coder.decodeInteger(forKey: "selectionIndex") tableArrayController.setSelectionIndex(index) tableView.scrollRowToVisible(index) updateSelectedCharacterDisplays() } -} \ No newline at end of file +} diff --git a/Tesseract-Box-Editor/ImageView.swift b/Tesseract-Box-Editor/ImageView.swift index 06536a1..908afd3 100644 --- a/Tesseract-Box-Editor/ImageView.swift +++ b/Tesseract-Box-Editor/ImageView.swift @@ -34,8 +34,8 @@ class ImageView: ImageViewWithSelectionRect override init(frame frameRect: NSRect) { super.init(frame: frameRect) - self.fillColor = NSColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 0.5).CGColor - self.strokeColor = NSColor.redColor().CGColor + self.fillColor = NSColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 0.5).cgColor + self.strokeColor = NSColor.red.cgColor self.duration = 4.0 self.lineDashPattern = [2, 1] @@ -45,4 +45,4 @@ class ImageView: ImageViewWithSelectionRect fatalError("init(coder:) has not been implemented") } -} \ No newline at end of file +} diff --git a/Tesseract-Box-Editor/ImageViewWithSelectionRect.swift b/Tesseract-Box-Editor/ImageViewWithSelectionRect.swift index 0cb53b5..2654373 100644 --- a/Tesseract-Box-Editor/ImageViewWithSelectionRect.swift +++ b/Tesseract-Box-Editor/ImageViewWithSelectionRect.swift @@ -37,22 +37,22 @@ class ImageViewWithSelectionRect: NSImageView var selectionHandleLayers: [CAShapeLayer] = [] var drawSelectionHandles = false - var cropPoint = CGPointZero + var cropPoint = CGPoint.zero var selectionRect = NSZeroRect - var strokeColor = NSColor.blackColor().CGColor - var fillColor = NSColor.clearColor().CGColor + var strokeColor = NSColor.black.cgColor + var fillColor = NSColor.clear.cgColor var lineDashPattern = [10, 15] var duration = 0.75 var numberHandles = 4 - func setupAnimatedSelectionRect(rect: NSRect) + func setupAnimatedSelectionRect(_ rect: NSRect) { selectionLayer = createAnimationLayer() layer!.addSublayer(selectionLayer) - selectionLayer.addAnimation(createAnimation(), forKey: "linePhase") + selectionLayer.add(createAnimation(), forKey: "linePhase") selectionLayer.transform = createTransform(self.cropPoint) @@ -68,15 +68,16 @@ class ImageViewWithSelectionRect: NSImageView return } - func drawSelectionRect(rect: NSRect) + func drawSelectionRect(_ rect: NSRect) { - let path = CGPathCreateMutable() + let path = CGMutablePath() - CGPathMoveToPoint(path, nil, rect.origin.x, rect.origin.y) - CGPathAddLineToPoint(path, nil, rect.origin.x, rect.origin.y + rect.size.height) - CGPathAddLineToPoint(path, nil, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height) - CGPathAddLineToPoint(path, nil, rect.origin.x + rect.size.width, rect.origin.y) - CGPathCloseSubpath(path) + path.move(to: rect.origin) + path.addLine(to: CGPoint(x: rect.origin.x, y: rect.origin.y + rect.size.height)) + path.addLine(to: CGPoint(x: rect.origin.x + rect.size.width, y: rect.origin.y + rect.size.height)) + path.addLine(to: CGPoint(x: rect.origin.x + rect.size.width, y: rect.origin.y)) + + path.closeSubpath() selectionLayer.path = path } @@ -88,7 +89,7 @@ class ImageViewWithSelectionRect: NSImageView shapeLayer.lineWidth = 0.5 shapeLayer.strokeColor = strokeColor shapeLayer.fillColor = fillColor - shapeLayer.lineDashPattern = lineDashPattern + shapeLayer.lineDashPattern = lineDashPattern as [NSNumber] return shapeLayer @@ -100,14 +101,14 @@ class ImageViewWithSelectionRect: NSImageView dashAnimation.fromValue = 0.0 dashAnimation.toValue = 15.0 dashAnimation.duration = duration - dashAnimation.cumulative = true + dashAnimation.isCumulative = true dashAnimation.repeatCount = HUGE return dashAnimation } - func createTransform(cropPoint: NSPoint) -> CATransform3D + func createTransform(_ cropPoint: NSPoint) -> CATransform3D { var verticalPadding: CGFloat = 0.0 var horizontalPadding: CGFloat = 0.0 @@ -144,7 +145,7 @@ class ImageViewWithSelectionRect: NSImageView return transform } - func drawHandles(rect: NSRect) + func drawHandles(_ rect: NSRect) { var handles: [NSPoint] = [] @@ -164,23 +165,24 @@ class ImageViewWithSelectionRect: NSImageView setupSelectionHandleLayers() } - for var i = 0; i < handles.count; i++ + for i in 0 ..< handles.count { drawHandle(handles[i], layer: selectionHandleLayers[i]) } } - func drawHandle(point: NSPoint, layer: CAShapeLayer) + func drawHandle(_ point: NSPoint, layer: CAShapeLayer) { let size: CGFloat = 0.5 - let path = CGPathCreateMutable() + let path = CGMutablePath() + + path.move(to: CGPoint(x: point.x - size, y: point.y - size)) + path.addLine(to: CGPoint(x: point.x - size, y: point.y + size)) + path.addLine(to: CGPoint(x: point.x + size, y: point.y + size)) + path.addLine(to: CGPoint(x: point.x + size, y: point.y - size)) - CGPathMoveToPoint(path, nil, point.x - size, point.y - size) - CGPathAddLineToPoint(path, nil, point.x - size, point.y + size) - CGPathAddLineToPoint(path, nil, point.x + size, point.y + size) - CGPathAddLineToPoint(path, nil, point.x + size, point.y - size) - CGPathCloseSubpath(path) + path.closeSubpath() layer.path = path @@ -188,12 +190,12 @@ class ImageViewWithSelectionRect: NSImageView func setupSelectionHandleLayers() { - for var i = 0; i < numberHandles; i++ + for _ in 0 ..< numberHandles { let layer = CAShapeLayer() layer.lineWidth = 0.1 - layer.strokeColor = NSColor.blueColor().CGColor - layer.fillColor = NSColor.blueColor().CGColor + layer.strokeColor = NSColor.blue.cgColor + layer.fillColor = NSColor.blue.cgColor layer.transform = selectionLayer.transform selectionHandleLayers.append(layer) @@ -209,11 +211,11 @@ class ImageViewWithSelectionRect: NSImageView layer.removeFromSuperlayer() } - selectionHandleLayers.removeAll(keepCapacity: true) + selectionHandleLayers.removeAll(keepingCapacity: true) selectionLayer = nil } - func computeResizedSelectionRectangle(index: Int, dragPoint: NSPoint) -> NSRect + func computeResizedSelectionRectangle(_ index: Int, dragPoint: NSPoint) -> NSRect { var left = Int(selectionRect.origin.x) var right = Int(selectionRect.origin.x + selectionRect.size.width) @@ -236,29 +238,32 @@ class ImageViewWithSelectionRect: NSImageView } // Coordinates are inverted in this function. (0, 0) is the upper left and y increases down - func trimImage(image: NSImage) + func trimImage(_ image: NSImage) { - let imageRef = image.CGImageForProposedRect(nil, context: nil, hints: nil)?.takeUnretainedValue() - let width = CGImageGetWidth(imageRef) - let height = CGImageGetHeight(imageRef) + if let imageRef = image.cgImage(forProposedRect: nil, context: nil, hints: nil) { //.takeUnretainedValue() + let width = imageRef.width + let height = imageRef.height let colorSpace = CGColorSpaceCreateDeviceRGB() let bytesPerPixel: Int = 4 let bytesPerComponent: Int = 8 let rawData = calloc(height * width * bytesPerPixel, 1) - let pointer = UnsafePointer(rawData) + if rawData == nil { + return + } + let pointer = rawData!.assumingMemoryBound(to: UInt8.self) let bytesPerRow = bytesPerPixel * width - let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue | CGBitmapInfo.ByteOrder32Big.rawValue) - let context = CGBitmapContextCreate(rawData, width, height, bytesPerComponent, bytesPerRow, colorSpace, bitmapInfo.rawValue) + let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue) + let context = CGContext(data: rawData, width: width, height: height, bitsPerComponent: bytesPerComponent, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) - CGContextDrawImage(context, CGRect(x: 0, y: 0, width: Int(width), height: Int(height)), imageRef) + context?.draw(imageRef, in: CGRect(x: 0, y: 0, width: Int(width), height: Int(height))) var top = 0 var left = 0 var right = Int(width) var bottom = Int(height) - for var x = 0; x < Int(width); x++ + for x in 0 ..< Int(width) { if scanColumn(x, height: Int(height), width: Int(width), pointer: pointer) { @@ -267,7 +272,7 @@ class ImageViewWithSelectionRect: NSImageView } } - for var x = Int(width) - 1; x >= 0; x-- + for x in (Int(width) - 1)...0 { if scanColumn(x, height: Int(height), width: Int(width), pointer: pointer) { @@ -276,7 +281,7 @@ class ImageViewWithSelectionRect: NSImageView } } - for var y = 0; y < Int(height); y++ + for y in 0 ..< Int(height) { if scanRow(y, width: Int(width), pointer: pointer) { @@ -285,7 +290,7 @@ class ImageViewWithSelectionRect: NSImageView } } - for var y = Int(height) - 1; y >= 0; y-- + for y in (Int(height) - 1)...0 { if scanRow(y, width: Int(width), pointer: pointer) { @@ -304,14 +309,15 @@ class ImageViewWithSelectionRect: NSImageView let bitmapRep = NSBitmapImageRep(focusedViewRect: cropRect) image.unlockFocus() - let croppedImage = NSImage(data: bitmapRep!.representationUsingType(.NSPNGFileType, properties: [:])!) + let croppedImage = NSImage(data: bitmapRep!.representation(using: .png, properties: [:])!) cropPoint = cropRect.origin self.image = croppedImage } + } - func scanRow(y: Int, width:Int, pointer: UnsafePointer) -> Bool + func scanRow(_ y: Int, width:Int, pointer: UnsafePointer) -> Bool { - for var x = 0; x < width; x++ + for x in 0 ..< width { if pointer[(x + y * width) * 4] != 0xff // only check red, could cause trouble { @@ -321,9 +327,9 @@ class ImageViewWithSelectionRect: NSImageView return false } - func scanColumn(x: Int, height: Int, width: Int, pointer: UnsafePointer) -> Bool + func scanColumn(_ x: Int, height: Int, width: Int, pointer: UnsafePointer) -> Bool { - for var y = 0; y < height; y++ + for y in 0 ..< height { if pointer[(x + y * width) * 4] != 0xff // only check red {