D言語からObjective-CとCocoaAPIを使いたい
BezierPath 図形を表示します
「MacOS X プログラミング入門 Cocoa + Java (2001年)」の FirstBezier を参考にしました。
アイコンとCredits.rtfを作って、aboutPanelを設定してみました。


サンプルコード
Powered by Prism
flower/dub.json
{
"authors": ["hidhok"],
"description": "A D/Objective-C Cocoa application.",
"name": "flower",
"dflags": ["-L-framework", "-LCocoa"],
"sourceFiles": ["../cocoa/window",
"../cocoa/control",
"../cocoa/menus"]
}
flower/source/app.d
/**
* flower/source/app.d Version 0.0.3 Bezier View Sample Program
*/
module flower.main;
import core.attribute : optional, selector;
import std.stdio;
import std.conv;
import std.format;
import std.math;
import cocoa.window;
import cocoa.control;
import cocoa.menus;
string appName;
string versionNo = "0.0.3";
string helpMessage = "CocoaAPIを使用して、\nBezier曲線図形を\nD言語で表示しています。"
~ "\naboutPanel に Options を加えてみました。";
NSWindow win;
BezierView bzView;
NSScrollView scrView;
Label[3] sldVal;
double scaleFactor = 1;
int numbers = 15;
double distance = 0;
double transparency = 0.3;
void main() {
auto delegate_ = AppDelegate.alloc.init;
NSApp.delegate_ = cast(void*) delegate_;
NSApp.activationPolicy = NSAppActivationPolicy.regular;
NSApp.run;
}
extern (Objective-C)
class ViewController : NSViewController, NSWindowDelegate {
override static ViewController alloc() @selector("alloc");
override ViewController init() @selector("init");
override void loadView() @selector("loadView") {
printf("loadView\n");
}
override void viewDidLoad() @selector("viewDidLoad") {
printf("viewDidLoad\n");
}
void winDidResize(NSNotification) @selector("windowDidResize:") {
bzView.needsDisplay = true;
bzView.setZoomToCenter; // error回避のため順序を入れ替えました
}
}
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 true;
}
void applicationDidFinishLaunching(NSNotification notification)
@selector("applicationDidFinishLaunching:") {
buildWindow;
buildContents;
}
void aboutPanel() @selector("aboutPanel") {
// dialog(appName, "Version " ~ versionNo);
aboutPanelOpt;
}
void aboutPanelOpt() @selector("aboutPanelOpt") {
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("1".toNs, "ApplicationVersion".toNs);
NSApplication.shared_.aboutPanelOptions(options.copy);
}
void showHelp() @selector("showHelp") {
dialog("Help", helpMessage);
}
}
void buildWindow() {
appName = NSProcessInfo.processInfo.processName.toDs;
NSApp.menu = smallMenu(appName);
NSRect w_rect = nRect(150, 500, 300, 400);
immutable w_style = NSWindowStyleMask.titled |
NSWindowStyleMask.closable |
NSWindowStyleMask.resizable |
NSWindowStyleMask.miniaturizable;
win = NSWindow.alloc.init(w_rect, w_style, backing.buffered, false);
win.title = (appName ~ " (D言語)").toNs;
win.minSize = NSSize(200, 328);
win.bgColor = NSColor.white;
ViewController vCtrler = ViewController.alloc.init;
vCtrler.view.subview = win.contentView;
win.delegate_ = vCtrler;
win.makeKeyAndOrderFront = null;
NSApp.activateIgnoringOtherApps = true;
}
void buildContents() {
/* ScrollView ClipView BezierView */
scrView = NSScrollView.alloc.init(nRect(0, 100, 300, 300));
scrView.resizeMask = ResizeMask.Width | ResizeMask.Height;
win.contentView.subview = scrView;
NSClipView cpView = NSClipView.alloc.init;
scrView.contentView = cpView;
bzView = BezierView.alloc.init(nRect(0, 0, 300, 300));
cpView.subview = bzView;
/* slider label */
Slider[3] slider;
Label[3] sldTitle;
string[3] titleStr = ["Numbers", "Distance", "Transparency"];
double[3][3] startVals = [[15, 1.0, 100], [0, -30, 60.0], [0.3, 0.01, 1]];
double[3][3] tp = [[18, 60, 82], [23, 35, 77], [10, 10, 90]];
foreach(i; 0..3) {
sldTitle[i] = Label.alloc.init(nRect(tp[i][0], tp[i][1], tp[i][2], 25));
slider[i] = Slider.alloc.init(nRect(140, 60 - i * 25, 150, 25));
slider[i].setValues(startVals[i][0], startVals[i][1], startVals[i][2]);
slider[i].action_ = "sliderAction" ~ i.to!string; //
sldTitle[i].text = format("%13s", titleStr[i]);
sldVal[i] = Label.alloc.init(nRect(100, 60 - i * 25, 40, 25));
sldVal[i].text = format("%5.2f", startVals[i][0]);
}
sldVal[0].text = format("%5.0f", startVals[0][0]);
}
extern (Objective-C)
class Slider : NSSlider {
override static Slider alloc() @selector("alloc");
override Slider init(NSRect) @selector("initWithFrame:");
void setValues(double start, double min, double max)
@selector("setValues:min:max:") {
this.resizeMask = ResizeMask.Width;
this.target = this;
this.continuous = true;
this.maxValue = max;
this.minValue = min;
this.value = start;
this.sliderType = NSSliderType.Linear;
this.vertical = false;
win.contentView.subview = this;
}
void sliderAction0() @selector("sliderAction0") {
numbers = this.value.to!int;
sldVal[0].text = format("%5d", numbers);
bzView.needsDisplay = true;
}
void sliderAction1() @selector("sliderAction1") {
distance = this.value;
sldVal[1].text = format("%5.1f", distance);
bzView.needsDisplay = true;
}
void sliderAction2() @selector("sliderAction2") {
transparency = this.value;
sldVal[2].text = format("%5.2f", transparency);
bzView.needsDisplay = true;
}
}
extern (Objective-C)
class Label : NSTextField {
override static Label alloc() @selector("alloc");
override Label init(NSRect) @selector("initWithFrame:");
void text(string labelStr) @selector("setValuesText:") {
this.bgColor = NSColor.clear;
this.bordered = false;
this.editable = false;
this.selectable = false;
this.str = labelStr;
win.contentView.subview = this;
}
}
extern (Objective-C)
class BezierView : NSView {
override static BezierView alloc() @selector("alloc");
override BezierView init() @selector("init");
override BezierView init(NSRect) @selector("initWithFrame:");
override void drawRect(NSRect rect) @selector("drawRect:") {
NSBezierPath bzPath;
double radian, cx = 150, cy = 150;
foreach(int i; 0 .. numbers) {
bzPath = NSBezierPath.bezierPath;
radian = i * 2 * PI / numbers;
bzPath.moveToPoint = iPoint(nP(10, 150 - distance), radian);
NSPoint p1 = iPoint(nP(290, 150 + distance), radian);
NSPoint p2 = nP(10, 290 - distance * 2);
NSPoint p3 = nP(290 - distance * 2, 10);
bzPath.curveToPoint(p1, p2, p3);
NSColor.colorHSB(1.0 * i / numbers, 1.0, 1.0, transparency).set;
bzPath.fill;
}
}
void setZoomToCenter() @selector("setZoomToCenter") {
double scrW, scrH, bzW = 300, bzH = 300;
scrW = scrView.frame.size.width;
scrH = scrView.frame.size.height;
double sf = scrW < scrH ? (scrW / bzW) : (scrH / bzH);
NSRect frame = this.frame;
NSRect bounds = this.bounds;
frame.size.width = bzW * sf;
frame.size.height = bzH * sf;
this.frame = frame;
this.bounds = bounds;
double ox, oy;
if (scrW < scrH) {
ox = 0;
oy = (scrH - scrW) / 2;
} else {
ox = (scrW - scrH) / 2;
oy = 0;
}
this.frameOrigin = nP(ox, oy);
}
}
NSPoint iPoint(NSPoint pt, double radian) {
double X = pt.x - 150;
double Y = pt.y - 150;
double M = sqrt(X * X + Y * Y);
double R = atan(Y / X);
X = M * cos(R + radian);
Y = M * sin(R + radian);
return NSPoint(X + 150, Y + 150);
}
NSPoint nP(double x, double y) {
return NSMakePoint(x, y);
}
cocoa/window.d
cocoa/control.d
cocoa/menus.d
- Log
- 2024-06-07 修正しました
- 2024-03-05 追加・修正しました
- 2024-01-25 upload