D言語からObjective-CとCocoaAPIを使いたい

直線の破線、一点鎖線、二点鎖線を描画します

D言語の配列を、C言語の配列に変換し、Objective-Cに渡します。

setLineDashのSample

サンプルコード

Powered by Prism

dashline/dub.json
                        
{
    "authors": ["hidhok"],
    "description": "A D/Objective-C Cocoa application.",
    "name": "dashline",
    "dflags": ["-L-framework", "-LCocoa"],
    "sourceFiles": ["../cocoa/window",
                    "../cocoa/control",
                    "../cocoa/menus"]
}               
dashline/source/app.d

/**
 *   dashline/source/app.d   Version 0.0.8
 *      Cocoa Drawing Guide : Paths (Documentation Archive : Apple)
 */
module dashline.main;
import core.attribute : optional, selector;
import std.conv : to;
import std.format;
import std.math;
import std.stdio : printf;
import cocoa.window;
import cocoa.menus;

string appName;
string versionNo = "0.0.8";
string helpMessage = "CocoaAPIを使用して、点線・破線 を\nD言語で表示しています。";

void main() {
    auto delegate_ = AppDelegate.alloc.init;
    NSApp.delegate_ = cast(void*) delegate_;
    NSApp.activationPolicy = NSAppActivationPolicy.regular;
    NSApp.run;
}

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 rect) @selector("drawRect:") {
        void print(string str, CGFloat x, CGFloat y) { 
            str.toNs.drawAtPoint(NSPoint(x, y), null); }
        NSColor.white.set;
        NSRectFill(rect);
        print("破線、一点鎖線、二点鎖線 及び 線端末の形状", 90, 360);
        print("line width", 70, 330);

        NSBezierPath.defaultLineWidth = 0.1;
        for (int i = 0; i < 10; i++) {
            NSBezierPath path = NSBezierPath.bezierPath;
            path.moveToPoint(NSPoint(40 + 30 * i, 40));
            path.lineToPoint(NSPoint(140 + 30 * i, 320));
            path.lineWidth(cast(CGFloat)i);
            CGFloat[] pattern;
            if (i < 3) {
                NSColor.blue.stroke;
                pattern = [4, 6];  // 破線
            } else if (i < 6) {
                NSColor.red.stroke;
                pattern = [40, 10, 6, 10];  // 一点鎖線
            } else {
                NSColor.green.stroke;
                pattern = [40, 12, 8, 12, 8, 12];  // 二点鎖線
                path.lineCapStyle(i - 7);
            } 
            path.lineDashPattern(pattern);
            path.stroke;
            print(i.to!string, 140 + i * 30, 330);
        }
        print("line wide 0 では default に設定した0.1の線幅が表示されます。", 70, 10);
    }
}

void lineDashPattern(NSBezierPath p, CGFloat[] pattern) {
    CGFloat offset = 0;
    NSInteger count = cast(long)pattern.length;
    p.dash(pattern.ptr, count, offset);
}

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;
    }
    void aboutPanel() @selector("aboutPanel") {
        dialog(appName, "Version " ~ versionNo);
    }
    void showHelp() @selector("showHelp") {
        dialog("Help", helpMessage);
    }
}

void buildWindow() {
    NSWindow win;
    NSRect w_rect = NSMakeRect(100, 550, 500, 400);
    appName = NSProcessInfo.processInfo.processName.toDs;
    NSApp.menu = miniMenu(appName);
    immutable w_style = NSWindowStyleMask.titled |
                        NSWindowStyleMask.closable |
                        NSWindowStyleMask.miniaturizable;
    win = NSWindow.alloc.init(w_rect, w_style, backing.buffered, false);
    win.title = (appName ~ " (D言語テスト)").toNs;
    DrawView dView = DrawView.alloc.init;
    win.contentView = dView;
    ViewController vCtrler = ViewController.alloc.init;
    vCtrler.view.subview = dView;
    win.makeKeyAndOrderFront = null;
    NSApp.activateIgnoringOtherApps = true;
}

extern (Objective-C) 
class ViewController : NSViewController {
    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");
    }
}               
cocoa/window.d
cocoa/control.d
cocoa/menus.d