GNUStepSwiftBridge
discuss-gnustep mailing list(https://mail.gnu.org/archive/html/discuss-gnustep/)
の8月のリストに、以下のような投稿がありました。
Swift calling into GNUStep Progress
github: https://github.com/austintatiousness/GNUStepSwiftBridge
このスレッドに中に、swift から GNUstep gui を呼び出した画像があります。
この gui 呼出しにトライしてみました。
実行結果
(ウィンドウサイズ等は変えてあります)
以下がその方法です。
GNUstep
GNUStepSwiftBridge project には、
This project is a Swift interface for GNUStep's version of AppKit.
This project assumes that you are running OnFlapp's GNUStep Desktop project.
とあります。
そこで、 OnFlapp's GNUStep Desktop をインストールしておきます。
OnFlapp's GNUStep Desktop https://github.com/onflapp/gs-desktop
インストールは、記された手順通りにすれば、問題なく行えます。
Lubuntuの repo からのインストールと異なり、システムのルートディレクトリに
/Applications , /Developer , /Library , /System が作成され、そこにインストール
される。
Swift
Linux のシステムは、これまで使用している Lubuntu をそのまま利用します。
Swiftは、バージョンを5.8.1 にして、前回同様インストールします。
GNUStepSwiftBridge
上記の github からダウンロードし、任意の場所に保存します。
準備が整ったら、GNUStepSwiftBridge のルートディレクトリから、
swift run NSWindowTest
と実行します。import AppKit のエラーが出ます。
これは、AppKit ライブラリを呼び出していますが、このプロジェクト内に
AppKit ライブラリが定義されていません。ライブラリが期待される場所(Sources/AppKit)に AppKit.swift がありますが、内容がライブラリと異なっています。
その関連を調べていたら、update メッセージの中にそれらしきものがありました。
それをもとに書き直した AppKit.swift です。
AppKit.swift
// The Swift Programming Language // https://docs.swift.org/swift-book import FoundationGNUStep import libobjc2 import AppKitGNUStep import ObjCSwiftInterop //NSApplication open class NSApplication: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSApplication" } public var shared: NSApplication { get { var sharedApp = forSwift_objcSendMessage(&self._nsobjptr!.pointee, sel_registerName("sharedApplication")) return NSApplication() } } } open class NSApplicationDelegate: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSApplicationDelegateForSwift" } static var didFinishLaunchingIMP: @convention(block) (UnsafeMutablePointer<objc_object>?,SEL,id?) -> (UInt8) = { first, second, third in let SELF: NSApplicationDelegate? = smart_swift_lookupIvarWithType(_nsobjptr: first, name: "___swiftPtr") SELF?.applicationDidFinishLaunching(notification: nil) return 0 } open func applicationDidFinishLaunching(notification: Any?) { } static var _objcClass = GNUStepNSObjectSubclassConstructor(name: "NSApplicationDelegateForSwift", superName: "NSObject", create: { ptr in var types = "i@:@" let imp = imp_implementationWithBlock(unsafeBitCast(didFinishLaunchingIMP, to: id.self)) class_addMethod(ptr, sel_registerName("applicationDidFinishLaunching:"),imp, types) }) public override init() { _ = NSApplicationDelegate._objcClass super.init() var nclass = objc_getClass("NSApplicationDelegateForSwift") var initalizedObject = forSwift_objcSendMessage(&nclass!.pointee, sel_getUid("alloc")) initalizedObject = forSwift_objcSendMessage(&initalizedObject!.pointee, sel_getUid("init")) self._nsobjptr = initalizedObject var cast = Unmanaged.passUnretained(self).toOpaque() smart_swift_setIvar(_nsobjptr: self._nsobjptr, name: "___swiftPtr", value: cast) } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init(nsobjptr: nsobjptr) } public func didFinishLaunching(_ OBJ: Any, notification: Any?) -> Void { } } open class UIView: NSView { public override var _nsclassName: String { return "UIView" } static var isFlippedIMP: @convention(block) (UnsafeMutablePointer<objc_object>?,SEL) -> (UInt8) = { first, second in print("!!!!!!!!!!!!!!!!!!!!!!!!asked if is flipped!") return 1 } static var _objcClass = GNUStepNSObjectSubclassConstructor( name: "UIView", superName: "NSScrollView", create: { ptr in } ) public override init() { _ = UIView._objcClass super.init() let nclass = objc_getClass("UIView") let types = "c" let imp = imp_implementationWithBlock(unsafeBitCast(UIView.isFlippedIMP, to: id.self)) class_replaceMethod(UIView._objcClass._nsobjptr!, sel_registerName("isFlipped"),imp, types) var initalizedObject = forSwift_objcSendMessage(&nclass!.pointee, sel_getUid("alloc")) initalizedObject = forSwift_objcSendMessage1NSRect(&initalizedObject!.pointee, sel_getUid("initWithFrame:"), CGRect(x: 0, y: 0, width: 100, height: 100)) initalizedObject = forSwift_objcSendMessage(&initalizedObject!.pointee, sel_getUid("retain")) self._nsobjptr = initalizedObject initalizedObject = forSwift_objcSendMessage(&initalizedObject!.pointee, sel_getUid("_rebuildCoordinates")) let cast = Unmanaged.passUnretained(self).toOpaque() smart_swift_setIvar(_nsobjptr: self._nsobjptr, name: "___swiftPtr", value: cast) } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init() self._nsobjptr = nsobjptr var initalizedObject = forSwift_objcSendMessage(&nsobjptr!.pointee, sel_registerName("retain")) } } public class NSFont: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSFont" } public override init() { super.init() } public init?(name: String, size: Float) { super.init() var nsColorClass = objc_getClass("NSFont") var size = size var string = NSString(string: name) var imp: (@convention(c) (id, SEL, id, Float) -> (id?))? = objc_smart_getIMP(id: &nsColorClass!.pointee, selector: "fontWithName:size:") if var rtn = imp?(&nsColorClass!.pointee, sel_getUid("fontWithName:size:"), &string._nsobjptr!.pointee, size) { self._nsobjptr = rtn print("FOUND FONT") var initalizedObject = forSwift_objcSendMessage(&rtn.pointee, sel_registerName("retain")) } else { print("FONT NOT FOUND") return nil } } public static func boldSystemFontOfSize(size: Double) -> NSFont { var nsColorClass = objc_getClass("NSFont") var size = size var imp: (@convention(c) (id, SEL, Double) -> (id?))? = objc_smart_getIMP(id: &nsColorClass!.pointee, selector: "boldSystemFontOfSize:") if var rtn = imp?(&nsColorClass!.pointee, sel_getUid("boldSystemFontOfSize:"), size) { print("FOUND boldSystemFontOfSize") var initalizedObject = forSwift_objcSendMessage(&rtn.pointee, sel_registerName("retain")) return NSFont(nsobjptr: rtn) } else { return NSFont() } } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init() self._nsobjptr = nsobjptr var initalizedObject = forSwift_objcSendMessage(&nsobjptr!.pointee, sel_registerName("retain")) } } public class NSColor: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSColor" } public override init() { super.init() let nsColorClass = objc_getClass(self._nsclassName) var initalizedObject = forSwift_objcSendMessage(&nsColorClass!.pointee, sel_registerName("blueColor")) initalizedObject = forSwift_objcSendMessage(&initalizedObject!.pointee, sel_registerName("retain")) self._nsobjptr = initalizedObject } public init(red: Float, green: Float, blue: Float, alpha: Float) { super.init() let nsColorClass = objc_getClass(self._nsclassName) let red = red let green = green let blue = blue let alpha = alpha var initalizedObject = forSwift_objcSendMessage4Floats(&nsColorClass!.pointee, sel_registerName("colorWithCalibratedRed:green:blue:alpha:"), red, green, blue, alpha) initalizedObject = forSwift_objcSendMessage(&initalizedObject!.pointee, sel_registerName("retain")) self._nsobjptr = initalizedObject } public static var clear: NSColor { return .init(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.0) } public static var blue: NSColor { return .init(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0) } public static var black: NSColor { return .init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) } public static var white: NSColor { return .init(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) } public static var grey: NSColor { return .init(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0) } public static var darkPurple: NSColor { return NSColor.init(red: 0.1422559619, green: 0.05977959186, blue: 0.2294596732, alpha: 1) } public static var purple: NSColor { let c = NSColor.init(red: 0.2726541758, green: 0.1163508371, blue: 0.435738951, alpha: 1) return c } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init(nsobjptr: nsobjptr) } } open class NSImage: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSImage" } public static func image(named: String) -> NSImage? { print("finding image named \(named)") var nsColorClass = objc_getClass("NSImage") var nsColorClassAsClass = object_getClass(objc_getClass("NSImage")) var string = NSString(string: named) var imp: (@convention(c) (id, SEL, id) -> (id?))? = objc_smart_getIMP(id: &nsColorClass!.pointee, selector: "imageNamed:") print(imp) if var rtn = imp?(&nsColorClass!.pointee, sel_getUid("imageNamed:"), &string._nsobjptr!.pointee) { var initalizedObject = forSwift_objcSendMessage(&rtn.pointee, sel_registerName("retain")) let v = NSImage(nsobjptr: &rtn.pointee) print("image is named \(v.name)") return v } return nil } public var name: String { get { print("getting name") if var ptr = self._nsobjptr { var imp: (@convention(c) (id, SEL) -> (id))? = objc_smart_getIMP(object: self, selector: "name") if let rtn = imp?(&ptr.pointee, sel_getUid("name")) { if let rtn = objc_convertToSwift_NSObject(value: rtn) as? NSString { return rtn.string } } } return "" } } } open class NSView: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSView" } public var subviews: [Any] = [] public func addSubview(_ subview: NSView) { subviews.append(subview) guard let selfPtr = self._nsobjptr else {return} if var ptr = subview._nsobjptr{ _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("addSubview:"), &ptr.pointee) } } public func setBackgroundColor(_ color: NSColor) { guard let colorPtr = color._nsobjptr else {return} guard let selfPtr = self._nsobjptr else {return} _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setBackgroundColor:"), &colorPtr.pointee) } public var frame: CGRect { get { let imp: (@convention(c) (id, SEL) -> (CGRect))? = objc_smart_getIMP(object: self, selector: "frame") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("frame")) { return rtn } return .init(x: 0, y: 0, width: 0, height: 0) } set { guard let selfPtr = self._nsobjptr else {return} var imp: (@convention(c) (id, SEL, CGRect) -> (Void))? = objc_smart_getIMP(object: self, selector: "setFrame:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setFrame:"), newValue) } } public func setFrame(_ rect: CGRect) { print("set frame: \(rect)") guard let selfPtr = self._nsobjptr else {return} _ = forSwift_objcSendMessage1NSRect(&selfPtr.pointee, sel_registerName("setFrame:"), rect) } } public class NSWindow: GNUStepNSObjectWrapper { public override var _nsclassName: String { return "NSWindow" } public override init() { super.init() let nsWindowClass = objc_getClass(_nsclassName) var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, sel_registerName("alloc")) let styleMask: UInt = 1 + 2 + 4 + 8 let backingStoreType: UInt = 0 let deferr: Int8 = 0 let rect = CGRect(x: 200, y: 200, width: 500, height: 500) allocatedObject = initWithContentRect_styleMask_backing_defer(&allocatedObject!.pointee, sel_registerName("initWithContentRect:styleMask:backing:defer:"), rect, styleMask, backingStoreType, deferr) self._nsobjptr = allocatedObject self.setTitle(NSString(string: "Untitled Window")) } public init(_ rect: CGRect) { super.init() let nsWindowClass = objc_getClass(_nsclassName) var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, sel_registerName("alloc")) let styleMask: UInt = 1 + 2 + 4 + 8 let backingStoreType: UInt = 0 let deferr: Int8 = 0 allocatedObject = initWithContentRect_styleMask_backing_defer(&allocatedObject!.pointee, sel_registerName("initWithContentRect:styleMask:backing:defer:"), rect, styleMask, backingStoreType, deferr) self._nsobjptr = allocatedObject self.setTitle(NSString(string: "Untitled Window")) } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init(nsobjptr: nsobjptr) } public func orderFront(sender: Any?) { guard var ptr = self._nsobjptr else {return} _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("orderFront:"), nil) } public func setBackgroundColor(_ color: NSColor) { guard let colorPtr = color._nsobjptr else {return} guard let selfPtr = self._nsobjptr else {return} _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setBackgroundColor:"), &colorPtr.pointee) } var title: String { set { var title = NSString(string: newValue) if var ptr = title._nsobjptr, var selfPtr = self._nsobjptr { _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setTitle:"), &ptr.pointee) } } get { if let x: NSString = objc_smart_sendMessage(object: self, selector: "title", value1: StopVariable(), value2: StopVariable(), value3: StopVariable(), value4: StopVariable(), value5: StopVariable(), value6: StopVariable(), value7: StopVariable(), value8: StopVariable(), value9: StopVariable()) { return x.string } return "" } } public func setTitle(_ title: NSString) { if var ptr = title._nsobjptr, var selfPtr = self._nsobjptr { _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setTitle:"), &ptr.pointee) } } public var subviews: [Any] = [] public func addSubview(_ subview: GNUStepNSObjectWrapper) { subviews.append(subview) guard let selfPtr = self._nsobjptr else {return} var contentViewPtr = forSwift_objcSendMessage(&selfPtr.pointee, sel_registerName("contentView")) if var ptr = subview._nsobjptr, var contentViewPtr = contentViewPtr { _ = forSwift_objcSendMessage1(&contentViewPtr.pointee, sel_registerName("addSubview:"), &ptr.pointee) } } var contentView: NSView? public func setContentView(_ view: NSView) { guard let selfPtr = self._nsobjptr else {return} self.contentView = view if var ptr = view._nsobjptr { var _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setContentView:"), &ptr.pointee) _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("_invalidateCoordinates"), &ptr.pointee) _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("_rebuildCoordinates"), &ptr.pointee) } } public func printWindow() { guard let selfPtr = self._nsobjptr else {return} _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("print:"), nil) } public func setFrameOrigin(_ origin: ObjCSwiftInterop.NSPoint) { guard var ptr = self._nsobjptr else {return} var origin = origin _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("setFrameOrigin:"), &origin) } } public class NSControl: NSView { public func setEnabled(_ flag: Bool) { guard var ptr = self._nsobjptr else {return} var bool = flag _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("setEnabled:"), &bool) } public var stringValue: String { get { var imp: (@convention(c) (id, SEL) -> (id))? = objc_smart_getIMP(object: self, selector: "stringValue") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("stringValue")) { if let rtn = objc_convertToSwift_NSObject(value: rtn) as? NSString { return rtn.string } } return "" } set { guard var selfPtr = self._nsobjptr else {return} let ns = NSString(string: newValue) guard var stringPTR = ns._nsobjptr else {return} var imp: (@convention(c) (id, SEL, id) -> (Void))? = objc_smart_getIMP(object: self, selector: "setStringValue:") let rtn = imp?(&selfPtr.pointee, sel_getUid("setStringValue:"), &stringPTR.pointee) } } } public class NSImageView: NSView { public override var _nsclassName: String { return "NSImageView" } public override init() { super.init() var rect = ObjCSwiftInterop.CGRect(x: 0, y: 0, width: 200, height: 22) //(x: Double(50), y: Double(50), width: Double(50), height: Double(50)) let nsWindowClass = objc_getClass("NSImageView") var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, sel_registerName("alloc")) allocatedObject = forSwift_objcSendMessage1NSRect(&allocatedObject!.pointee, sel_registerName("initWithFrame:"), rect) _ = forSwift_objcSendMessage(&allocatedObject!.pointee, sel_registerName("retain")) self._nsobjptr = allocatedObject } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init() self._nsobjptr = nsobjptr var initalizedObject = forSwift_objcSendMessage(&nsobjptr!.pointee, sel_registerName("retain")) } public func setImage(_ image: NSImage) { print("Setting Image 1") guard var ptr = image._nsobjptr else {print("Setting Image image ptr == nil"); return} guard var selfPtr = self._nsobjptr else {print("Setting Image 1.2"); return} if var ptr = image._nsobjptr, var selfPtr = self._nsobjptr { print("Setting Image 2") _ = forSwift_objcSendMessage1ID(&selfPtr.pointee, sel_registerName("setImage:"), ptr) } } } public class NSButton: NSControl { static var _objcClass = GNUStepNSObjectSubclassConstructor(name: "NSButtonForSwift", superName: "NSButton", create: { ptr in}) public override var _nsclassName: String { return "NSButton" } static var ___private_actionIMP: @convention(block) (UnsafeMutablePointer<objc_object>?,SEL,id?) -> (Void) = { first, second, third in let SELF: NSButton? = smart_swift_lookupIvarWithType(_nsobjptr: first, name: "___swiftPtr") if let SELF = SELF { SELF.onAction?(SELF) } } public lazy var onAction: ((NSButton) -> (Void))? = { first in } public override init() { super.init() _ = Self._objcClass var rect = ObjCSwiftInterop.CGRect(x: 0, y: 0, width: 200, height: 22) //(x: Double(50), y: Double(50), width: Double(50), height: Double(50)) let nsWindowClass = objc_getClass("NSButtonForSwift") var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, sel_registerName("alloc")) allocatedObject = forSwift_objcSendMessage1NSRect(&allocatedObject!.pointee, sel_registerName("initWithFrame:"), rect) _ = forSwift_objcSendMessage(&allocatedObject!.pointee, sel_registerName("retain")) var types = "@" let imp = imp_implementationWithBlock(unsafeBitCast(NSButton.___private_actionIMP, to: id.self)) class_addMethod(object_getClass(&allocatedObject!.pointee), sel_registerName("___private_action:"),imp, types) _ = forSwift_objcSendMessage1ID(&allocatedObject!.pointee, sel_registerName("setTarget:"), allocatedObject!) var sel = sel_getUid("___private_action:") print("SEL = \(sel!)") _ = forSwift_objcSendMessage1SEL(&allocatedObject!.pointee, sel_registerName("setAction:"), sel!) self._nsobjptr = allocatedObject var cast = Unmanaged.passUnretained(self).toOpaque() print("in NSButton about to cast \(cast)") smart_swift_setIvar(_nsobjptr: self._nsobjptr, name: "___swiftPtr", value: cast) } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init(nsobjptr: nsobjptr) } public func setTitle(_ text: NSString) { if var ptr = text._nsobjptr, var selfPtr = self._nsobjptr { _ = forSwift_objcSendMessage1ID(&selfPtr.pointee, sel_registerName("setTitle:"), ptr) } } public func setImage(_ image: NSImage) { if var ptr = image._nsobjptr, var selfPtr = self._nsobjptr { _ = forSwift_objcSendMessage1ID(&selfPtr.pointee, sel_registerName("setImage:"), ptr) } } } public class NSTextField: NSControl { public override var _nsclassName: String { return "NSTextField" } public override init() { super.init() var rect = CGRect(x: 10, y: 10, width: 200, height: 50) let nsWindowClass = objc_getClass("NSTextField") var allocatedObject = forSwift_objcSendMessage(&nsWindowClass!.pointee, sel_registerName("alloc")) allocatedObject = forSwift_objcSendMessage1(&allocatedObject!.pointee, sel_registerName("initWithFrame:"), &rect) allocatedObject = forSwift_objcSendMessage(&allocatedObject!.pointee, sel_registerName("retain")) self._nsobjptr = allocatedObject self.setText(NSString(string: "This is me!")) } public required init(nsobjptr: UnsafeMutablePointer<objc_object>?) { super.init() self._nsobjptr = nsobjptr var initalizedObject = forSwift_objcSendMessage(&nsobjptr!.pointee, sel_registerName("retain")) } public func setText(_ text: NSString) { if var ptr = text._nsobjptr, var selfPtr = self._nsobjptr { _ = forSwift_objcSendMessage1(&selfPtr.pointee, sel_registerName("setStringValue:"), &ptr.pointee) } } public var font: NSFont? { get { var imp: (@convention(c) (id, SEL) -> (id))? = objc_smart_getIMP(object: self, selector: "font") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("font")) { return NSFont(nsobjptr: rtn) } return nil } set { print("SETTING FONT") guard let selfPtr = self._nsobjptr else {print("selfPtr = nil"); return} guard let newValuePtr = newValue?._nsobjptr else {print("newValue = nil \(newValue)"); return} var imp: (@convention(c) (id, SEL, id) -> (Void))? = objc_smart_getIMP(object: self, selector: "setFont:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setFont:"), &newValuePtr.pointee) } } public func setEditable(_ flag: Bool) { guard var ptr = self._nsobjptr else {return} var bool = flag _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("setEditable:"), &bool) } public func setSelectable(_ flag: Bool) { guard var ptr = self._nsobjptr else {return} var bool = flag _ = forSwift_objcSendMessage1(&ptr.pointee, sel_registerName("setSelectable:"), &bool) } public func selectText() { guard var ptr = self._nsobjptr else {return} _ = forSwift_objcSendMessage(&ptr.pointee, sel_registerName("selectText")) } public var isSelectable: Bool { get { var imp: (@convention(c) (id, SEL) -> (UInt8))? = objc_smart_getIMP(object: self, selector: "isSelectable") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("isSelectable")) { return rtn == 0 ? false : true } return true } set { guard let selfPtr = self._nsobjptr else {return} var imp: (@convention(c) (id, SEL, UInt8) -> (Void))? = objc_smart_getIMP(object: self, selector: "setSelectable:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setSelectable:"), newValue ? 1 : 0) } } public var isEditable: Bool { get { var imp: (@convention(c) (id, SEL) -> (UInt8))? = objc_smart_getIMP(object: self, selector: "isEditable") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("isEditable")) { return rtn == 0 ? false : true } return true } set { guard let selfPtr = self._nsobjptr else {return} let imp: (@convention(c) (id, SEL, UInt8) -> (Void))? = objc_smart_getIMP(object: self, selector: "setEditable:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setEditable:"), newValue ? 1 : 0) } } public var textColor: NSColor { get { var imp: (@convention(c) (id, SEL) -> (id))? = objc_smart_getIMP(object: self, selector: "textColor") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("textColor")) { return NSColor(nsobjptr: rtn) } return .blue } set { guard let selfPtr = self._nsobjptr else {return} guard let newValuePtr = newValue._nsobjptr else {return} var imp: (@convention(c) (id, SEL, id) -> (Void))? = objc_smart_getIMP(object: self, selector: "setTextColor:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setTextColor:"), &newValuePtr.pointee) } } public var isBordered: Bool { get { let imp: (@convention(c) (id, SEL) -> (UInt8))? = objc_smart_getIMP(object: self, selector: "isBordered") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("isBordered")) { return rtn == 0 ? false : true } return true } set { guard let selfPtr = self._nsobjptr else {return} let imp: (@convention(c) (id, SEL, UInt8) -> (Void))? = objc_smart_getIMP(object: self, selector: "setBordered:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setBordered:"), newValue ? 1 : 0) } } public var isBezeled: Bool { get { let imp: (@convention(c) (id, SEL) -> (UInt8))? = objc_smart_getIMP(object: self, selector: "isBezeled") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("isBezeled")) { return rtn == 0 ? false : true } return true } set { guard let selfPtr = self._nsobjptr else {return} let imp: (@convention(c) (id, SEL, UInt8) -> (Void))? = objc_smart_getIMP(object: self, selector: "setBezeled:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setBezeled:"), newValue ? 1 : 0) } } public var drawsBackground: Bool { get { let imp: (@convention(c) (id, SEL) -> (UInt8))? = objc_smart_getIMP(object: self, selector: "drawsBackground") if let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("drawsBackground")) { return rtn == 0 ? false : true } return true } set { guard let selfPtr = self._nsobjptr else {return} let imp: (@convention(c) (id, SEL, UInt8) -> (Void))? = objc_smart_getIMP(object: self, selector: "setDrawsBackground:") let rtn = imp?(&self._nsobjptr!.pointee, sel_getUid("setDrawsBackground:"), newValue ? 1 : 0) } } }
この AppKit.swift をライブラリとして利用できるように、Package.swift を編集
します。
Package.swift
// swift-tools-version: 5.8 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "HelloWorld", products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .executable( name: "HelloWorld", targets: ["HelloWorld"]), .executable( name: "NSWindowTest", targets: ["NSWindowTest"]), .library(name: "libobjc", targets: ["libobjc2"]), .library(name: "AppKitGNUStep", targets: ["AppKitGNUStep"]), .library(name: "FoundationGNUStep", targets: ["FoundationGNUStep"]), .library(name: "ObjCSwiftInterop", targets: ["ObjCSwiftInterop"]), .library(name: "AppKit", targets: ["AppKit"]), ], targets: [ // Targets are the basic building blocks of a package, defining a module or a test suite. // Targets can depend on other targets in this package and products from dependencies. .executableTarget( name: "HelloWorld", dependencies: ["libobjc2", "AppKitGNUStep", "ObjCSwiftInterop", "FoundationGNUStep", "AppKit"] //resources: [.copy("Resources")] ), .executableTarget( name: "NSWindowTest", dependencies: ["libobjc2", "AppKitGNUStep", "ObjCSwiftInterop", "FoundationGNUStep", "AppKit"] //resources: [.copy("Resources")] ), .target(name: "ObjCSwiftInterop"), .target( name: "AppKit", dependencies: ["libobjc2", "AppKitGNUStep", "ObjCSwiftInterop", "FoundationGNUStep"]), .systemLibrary(name: "libobjc2"), .systemLibrary(name: "AppKitGNUStep"), .systemLibrary(name: "FoundationGNUStep"), .testTarget( name: "HelloWorldTests", dependencies: ["HelloWorld"]), ] )
次の部分を追加しています。
products .library 文
targets .executableTarget dependencies
targets .target 文
NSWindowTest、HolloWorld の main.swift を以下のように編集します。
どちらも数行程、編集や追加を行っています。
NSWindowTest
main.swift
// The Swift Programming Language // https://docs.swift.org/swift-book import Foundation import FoundationGNUStep import libobjc2 import AppKitGNUStep import ObjCSwiftInterop import AppKit @main struct App { static var window = NSWindow() static var window2 = NSWindow() //static var label = NSLabel() static var label = NSTextField() static var button = NSButton() static func main() { print("Hello World Times Two") //var poolClass = objc_getClass("NSAutoreleasePool") //var poolClassAllocated = forSwift_objcSendMessage(&objc_getClass("NSAutoreleasePool")!.pointee, sel_registerName("alloc")) //_ = forSwift_objcSendMessage(&poolClassAllocated!.pointee, sel_registerName("init")) let napClass = objc_getClass("NSApplication") var sharedApp = forSwift_objcSendMessage(&napClass!.pointee, sel_registerName("sharedApplication")) App.window.orderFront(sender: nil) App.window.setBackgroundColor(NSColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 0.5)) App.label.frame = .init(x: 20, y: 20, width: 200, height: 32) App.label.setBackgroundColor(NSColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0)) App.window.addSubview(App.label) let image = NSImage.image(named: "Dummy") App.button.frame = .init(x: 50, y: 100, width: 100, height: 30) App.window2.orderFront(sender: nil) App.window2.setFrameOrigin(NSPoint(x: 300, y: 300)) App.window2.setTitle(NSString(string: "Window 2")) App.window2.addSubview(App.button) //App.window.printWindow() //window.setBackgroundColor(NSColor()) //'UnsafeMutablePointer<Int8> //UnsafeMutablePointer<UnsafePointer<CChar>?> //return return NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv.pointee) } }
下の2行を追加しています。
1 App.label.frame = .init(x: 20, y: 20, width: 200, height: 32)
この行がないと、TextField が表示されない。
2 let image = NSImage.image(named: "Dummy")
この行がないと、Button 生成でコアダンプが起きる。
App.button の前に必要。
HolloWorld
main.swift
// The Swift Programming Language // https://docs.swift.org/swift-book import Foundation import FoundationGNUStep import libobjc2 import AppKitGNUStep import ObjCSwiftInterop import AppKit class AppDelegate: NSApplicationDelegate { //lazy var window = NSWindow() //lazy var newWindow = NSWindow() lazy var window = NSWindow(CGRect(x: 150, y: 300, width: 550, height: 450)) lazy var newWindow = NSWindow(CGRect(x: 100, y: 100, width: 400, height: 400)) lazy var button = NSButton() lazy var imageView = NSImageView() lazy var button2 = NSButton() lazy var button3 = NSButton() lazy var newWindowButton = NSButton() lazy var textField = NSTextField() lazy var image = NSImage.image(named: "Terminal.tiff") lazy var textField2 = NSTextField() lazy var view = UIView() override func applicationDidFinishLaunching(notification: Any?) { window.orderFront(sender: self) window.setTitle(NSString(string: "Hello Window")) view.frame = .init(x: 0, y: 0, width: 500, height: 450) newWindowButton.setTitle(NSString(string: "Show Window")) newWindowButton.frame = .init(x: 10, y: 22, width: 100, height: 32) newWindowButton.onAction = { button in self.newWindow.orderFront(sender: self) self.newWindow.setBackgroundColor(.purple) } view.addSubview(newWindowButton) imageView.frame = .init(x: 340, y: 22, width: 32, height: 32) imageView.setImage(self.image!) view.addSubview(imageView) button.setTitle(NSString(string: "Get Frame")) button.frame = .init(x: 120, y: 22, width: 100, height: 32) button.onAction = { button in self.textField.stringValue = "\(self.view.frame)" } view.addSubview(button) button2.setTitle(NSString(string: "Set Other Window")) button2.frame = .init(x: 230, y: 22, width: 100, height: 32) button2.onAction = { button in //self.view.frame = .init(x: 0, y: 32, width: 300, height: 300) self.newWindow.setBackgroundColor(.black) } view.addSubview(button2) button3.setImage(image!) button3.frame = .init(x: 430, y: 22, width: 100, height: 32) button3.onAction = { button in //self.view.frame = .init(x: 0, y: 32, width: 300, height: 300) //self.newWindow.setBackgroundColor(.black) self.newWindow.setBackgroundColor(.grey) } view.addSubview(button3) textField.setBackgroundColor(.clear) //textField.textColor = .init(red: 1.0, green: 1.0, blue: 0.0, alpha: 0.5) textField.textColor = .blue textField.isSelectable = false textField.isBordered = false textField.isBezeled = false textField.drawsBackground = false textField.frame = CGRect(x: 10, y: 100, width: 300, height: 32) //textField.text = "Click 'Get Frame'" textField.stringValue = "Click 'Get Frame'" textField.font = .boldSystemFontOfSize(size: 30) view.addSubview(textField) textField2.frame = CGRect(x: 10, y: 140, width: 300, height: 32) //textField2.text = "Some Cool Text" textField2.stringValue = "Some Cool Text" textField2.textColor = .white textField2.setBackgroundColor(.grey) view.addSubview(textField2) view.setBackgroundColor(.init(red: 1.0, green: 0.0, blue: 1.0, alpha: 1.0)) window.setContentView(view) } } @main struct App { //static var window = NSWindow() static var delegate = AppDelegate() //static var window2 = NSWindow() //static var label = NSTextField() static func main() { print("Hello World Times Two") App.delegate //var poolClass = objc_getClass("NSAutoreleasePool") //var poolClassAllocated = forSwift_objcSendMessage(&objc_getClass("NSAutoreleasePool")!.pointee, sel_registerName("alloc")) //_ = forSwift_objcSendMessage(&poolClassAllocated!.pointee, sel_registerName("init")) //https://stackoverflow.com/questions/24662864/swift-how-to-use-sizeof let napClass = objc_getClass("NSApplication") var sharedApp = forSwift_objcSendMessage(&napClass!.pointee, sel_registerName("sharedApplication")) print("Just created NSApplication") let v = forSwift_objcSendMessage1ID(&sharedApp!.pointee, sel_getUid("setDelegate:"), delegate._nsobjptr!) print("made it!") //window.setBackgroundColor(NSColor()) //'UnsafeMutablePointer<Int8> //UnsafeMutablePointer<UnsafePointer<CChar>?> //return return NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv.pointee) } }
1 TextField や Button は frame 設定がないと表示されない。
2 TextField の文字は text では表示されない。stringValue を用いる。
これで準備が整ったので、NSWindowTest と HelloWorld を実行します。
swift run NSWindowTest
swift run HelloWorld
NSWindowTest は実行できますが、HelloWorld ではコアダンプが起きます。
これは、ビルドされた実行ファイルがある場所に、gorm ファイルを含むResources
がないために起こっています。
この project site の最初に書いてあるように、Resources(NSWindowTest か HelloWorld のいずれか) を .build/debug にコピーします。(一度 swift run を実行しないと .build ディレクトリは作成されない。)今のところ、プログラムの中でコピーする方法が分かりません。
これで、 swift run を実行をすれば、正しく動作するはずです。
gorm ファイルのメニューも表示されます。
HolloWorld では、ボールドフォントのサイズ設定を行っています。
Lubuntu のシェルからの実行では、フォントが見つかりません。
/System/bin/startgsde を実行し、GWorkspace の Terminal から実行します。