D言語からObjective-CとCocoaAPIを使いたい
swin2 : swin の改版です
Code を分けました。Menu の Services 及び Preferences (環境設定) window、Web Help を設けました。
NSAlert で suppressionButton を実装しました。
コマンドラインからの文字列を表示します。

サンプルコード
Powered by Prism
swin2/dub.json
{
"authors": ["hidhok"],
"description": "A D/Objective-C Cocoa application.",
"name": "swin2",
"dflags": ["-L-framework", "-LCocoa"],
"sourceFiles": ["../cocoa/window",
"../cocoa/control",
"../cocoa/menu"]
}
swin2/source/app.d
/**
* swin2/source/app.d Version 0.1.3
*/
module swin2.main;
import core.attribute : optional, selector;
import std.stdio;
import std.conv : to;
import std.process : executeShell;
import cocoa.window;
import cocoa.control;
import cocoa.menu;
import swin2.view;
string appName;
string versionNo = "0.1.3";
string helpMessage = "CocoaAPIを使用して、\n" ~
"Labelを D言語で表示します。\nコマンドラインからの文字列も表示できます。";
NSWindow mainWin, prefWin, subWin;
SubWindowController prefCtrler;
bool prefWinFlag = false;
NSControlStateValue alertSupBtnState = state.Off;
void main(string[] args) {
auto delegate_ = AppDelegate.alloc.init;
NSApp.delegate_ = cast(void*) delegate_;
NSApp.activationPolicy = NSAppActivationPolicy.regular;
cmdLineProcess = args;
NSApp.run;
}
extern (Objective-C)
class AppDelegate : NSObject {
override static AppDelegate alloc() @selector("alloc");
override typeof(this) init() @selector("init");
bool applicationShouldTerminateAfterLastWindowClosed(
NSNotification notification) @selector(
"applicationShouldTerminateAfterLastWindowClosed:") {
// return alert("終了の確認", "アプリを終了しますか");
if (alertSupBtnState == state.On)
return true;
else
return alert("アプリを終了しますか", "Cancelでメインウインドに復帰します");
}
void applicationDidFinishLaunching(NSNotification notification)
@selector("applicationDidFinishLaunching:") {
buildMainWindow;
buildContents;
}
void aboutPanel() @selector("aboutPanel") {
NSMutableDictionary options = NSMutableDictionary.dictionary;
// NSImage img = NSImage.name("AppIcon.icns".toNs);
// options.setObjKey(img, "ApplicationIcon".toNs);
options.setObjKey(versionNo.toNs, "Version".toNs);
options.setObjKey("horkew.la.coocan.jp".toNs, "Copyright".toNs);
options.setObjKey(versionNo.toNs, "ApplicationVersion".toNs);
NSApplication.shared_.aboutPanelOptions(options.copy);
}
void showHelp() @selector("showHelp") {
dialog("Help", helpMessage);
}
void showWebHelp() @selector("showWebHelp") {
executeShell("open http://horkew.la.coocan.jp/D+CocoAPI/help.html");
}
void preferences() @selector("preferences") {
if (!prefWinFlag) {
prefWin = subWindow("環境設定", nRect(0, 0, 300, 200));
prefCtrler = SubWindowController.alloc.init(prefWin);
prefWinFlag = true;
prefCtrler.showWindow = prefWin;
}
}
void toolInstruments() @selector("toolInstruments") {
executeShell("open -a instruments");
}
void systemPreferences() @selector("systemPreferences") {
executeShell("open -a 'System Preferences'");
}
}
extern (Objective-C)
class SubWindowController : NSWindowController, NSWindowDelegate {
override static SubWindowController alloc() @selector("alloc");
override SubWindowController init(NSWindow) @selector("initWithWindow:");
override void showWindow(NSWindow win) @selector("showWindow:") {
win.delegate_ = this;
win.makeKeyAndOrderFront = null;
}
/* NSWindowDelegate */
void winWillClose(NSNotification) @selector("windowWillClose:") {
prefWinFlag = false;
}
void winDidResize(NSNotification) @selector("windowDidResize:");
}
NSWindow subWindow(string titleStr, NSRect winRect) {
immutable style = NSWindowStyleMask.titled | NSWindowStyleMask.closable;
subWin = NSWindow.alloc.init(winRect, style, backing.buffered, false);
subWin.title = titleStr.toNs;
subWin.center;
sView = SubView.alloc.init;
subWin.contentView = sView;
// sView.bgColor = colorGray(0.9); // no property
return subWin;
}
void buildMainWindow() {
appName = NSProcessInfo.processInfo.processName.toDs;
NSApp.menu = mainMenu(appName);
NSRect w_rect = NSMakeRect(100, 700, 300, 200);
immutable w_style = NSWindowStyleMask.titled |
NSWindowStyleMask.closable |
NSWindowStyleMask.resizable |
NSWindowStyleMask.miniaturizable;
mainWin = NSWindow.alloc.init(w_rect, w_style, backing.buffered, false);
mainWin.title = (appName ~ " (D言語)").toNs;
drView = DrawView.alloc.init;
// drView.bgColor = NSColor.white; // no property
mainWin.contentView = drView;
mainWin.minSize = NSMakeSize(230, 120);
mainWin.makeKeyAndOrderFront = null;
NSApp.activateIgnoringOtherApps = true;
}
bool alert(string message, string information) {
NSAlert al = NSAlert.alloc.init;
al.addButton("OK".toNs);
al.addButton("Cancel".toNs);
al.messageText(message.toNs);
al.information(information.toNs);
al.style = alertStyle.critical;
if (alertSupBtnState == state.Off) {
al.showSupBtn = true;
al.supBtn.title = "次回からこのメッセージを表示しない".toNs;
} else {
al.showSupBtn = false;
}
uint alResult = al.run;
if (al.supBtn.state == state.On) {
alertSupBtnState = state.On;
}
bool returnVal;
switch(alResult) {
case AlertReturn.OK:
returnVal = true;
break;
case AlertReturn.Cancel:
returnVal = false;
buildMainWindow; //
buildContents; //
break;
default:
returnVal = false;
break;
}
al.release;
return returnVal;
}
swin2/source/view.d
/**
* swin2/source/view.d
*/
module swin2.view;
import core.attribute : optional, selector;
import std.stdio;
import std.conv : to;
import cocoa.window;
import cocoa.control;
import swin2.main;
DrawView drView;
SubView sView;
string[] argStr;
string text = "Hello World!";
string urlStr = "http://horkew.la.coocan.jp/D+CocoAPI/rainbow.jpg";
void buildContents() {
Label label = Label.alloc.init(NSMakeRect(25, 25, 250, 150));
NSFont font = NSFont.nameSize("Times New Roman".toNs, 32);
label.attrStr = text.toAttrStr(font, NSColor.blue);
label.setValues;
}
void cmdLineProcess(string[] args) {
if (args.length > 1) {
argStr = args;
text = args[1];
}
}
extern (Objective-C)
class DrawView : NSView {
override static DrawView alloc() @selector("alloc");
override DrawView init() @selector("init");
override DrawView init(NSRect) @selector("initWithFrame:");
override void drawRect(NSRect) @selector("drawRect:");
override void keyDown(NSEvent event) @selector("keyDown:") { /* */ }
override bool acceptsFirstResponder() @selector("acceptsFirstResponder") {
return true;
}
}
extern (Objective-C)
class Label : NSTextField {
override static Label alloc() @selector("alloc");
override Label init() @selector("init");
override Label init(NSRect) @selector("initWithFrame:");
void setValues() @selector("setValues") {
this.editable = false;
this.selectable = false;
this.bordered = false;
this.drawsBg = true;
this.bgColor = colorGray(0.98);
this.resizeMask = ResizeMask.Width | ResizeMask.Height;
drView.subview = this;
}
}
NSColor colorGray(double e) {
return NSColor.rgba(e, e, e, 1);
}
/* KeyboardEvent.code values */
uint kVK_Escape = 0x0035; // = 53
extern (Objective-C)
class SubView : NSView {
override static SubView alloc() @selector("alloc");
override SubView init() @selector("init");
override SubView init(NSRect) @selector("initWithFrame:");
override void drawRect(NSRect rect) @selector("drawRect:");
override void keyDown(NSEvent event) @selector("keyDown:") {
if (event.keyCode == kVK_Escape)
subWin.close;
}
override bool acceptsFirstResponder() @selector("acceptsFirstResponder") {
return true;
}
}
cocoa/window.d
cocoa/control.d
cocoa/menu.d
- Log
- 2025-03-04 修正・訂正
- 2024-08-30 追加・訂正
- 2024-08-23 追加・訂正
- 2024-08-20 upload