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

NSColorWell を表示する

D言語から Mac の GUI を使用して NSColorWellとColorPanel を表示します。

「MacOS X プログラミング入門 Cocoa + Java (2001年)」を参考にしました。

NSColorWellのSample

サンプルコード

Powered by Prism

color/dub.json

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

/**
 *   color/source/app.d    Version 0.0.7
 */
module color.main;
import core.attribute : optional, selector;
import std.format;
import std.stdio;
import std.conv;
import cocoa.window;
import cocoa.control;
import cocoa.menus;

string appName;
string versionNo = "0.0.7";
View dView;
ColorWell cw;
NSTextField codeField;

void main() {
    auto delegate_ = AppDelegate.alloc.init;
    NSApp.delegate_ = cast(void*) delegate_;
    NSApp.activationPolicy = NSAppActivationPolicy.regular;
    NSApp.run;
}
                   
void buildWindow() {
	NSWindow win;
    appName = NSProcessInfo.processInfo.processName.toDs;
    NSApp.menu = miniMenu(appName);
    NSRect w_rect = NSMakeRect(0, 0, 300, 150);
    immutable w_style = NSWindowStyleMask.titled |
                        NSWindowStyleMask.closable |
                        NSWindowStyleMask.miniaturizable;
    win = NSWindow.alloc.init(w_rect, w_style, NSBacking.buffered, false);
    win.title = (appName ~ " (ColorWell Test)").toNs;
    win.moveTop = NSPoint(400, 900);
    ViewController vCtrler = ViewController.alloc.init;
    dView = View.alloc.init;
    vCtrler.view.subview = dView;
    win.contentView = dView;
    win.makeKeyAndOrderFront = null;
    NSApp.activateIgnoringOtherApps = true;
}

extern (Objective-C)
class View : NSView {
    override static View alloc() @selector("alloc");
    override View init() @selector("init");
    override View init(NSRect) @selector("initWithFrame:");
    override void drawRect(NSRect) @selector("drawRect:");
}

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");
    }
} 

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);
    }
    void showHelp() @selector("showHelp") {
        string helpMessage = "RGBカラーコードのコピペができます。\n"
                ~ "アルファ(透明度)の機能は未実装です。";
        dialog(appName ~ " Help", helpMessage);
    }
} 

void buildContents() {
   // Label
    NSFont labelFont = NSFont.nameSize("Helvetica".toNs, 20);
    Label label1 = Label.alloc.init(NSMakeRect( 30, 110, 120, 20));
    Label label2 = Label.alloc.init(NSMakeRect(160, 110, 120, 20));
    Label label3 = Label.alloc.init(NSMakeRect(170,  70, 100, 20));
    dView.subview = label1.textVal("Color Well", labelFont);
    dView.subview = label2.textVal("Color Code", labelFont);
    dView.subview = label3.textVal("R  G  B  α", labelFont);
   // ColorWell
    cw = ColorWell.alloc.init(NSMakeRect(30, 30, 100, 60));
    cw.setColorWellValues;
   // Field
    codeField = NSTextField.alloc.init(NSMakeRect(150, 30, 120, 30));
    cw.setColorCode;
}

extern (Objective-C)
class ColorWell : NSColorWell {
    override static ColorWell alloc() @selector("alloc");
    override ColorWell init(NSRect r) @selector("initWithFrame:");
    void setColorWellValues() @selector("setColorWellValues") {
        this.bordered = false;
        this.activate = true;
        this.target  = this;
        // this.action = sel_registerName("setColorCode".toCs); // 
        this.action_ = "setColorCode"; // 
        dView.subview = this;
    }
    void setColorCode() @selector("setColorCode") {
        codeField.font = NSFont.nameSize("Monaco".toNs, 20);
        codeField.target = this;
        // codeField.action = sel_registerName("readCode".toCs); //
        codeField.action_ = "readCode"; //
        ColorEncoder ce = new ColorEncoder;
        ce.encode = this;
        dView.subview = codeField;
    }
    void readCode() @selector("readCode") {
        string s = codeField.str.toDs; 
        // 入力無効文字の排除処理
        if (s.length == 0) s = "#ffffffff";
        if ('#' != s[0]) s = '#' ~ s;
        if (s.length > 8) s = s[0..9];
        if (s.length < 8) {
            while (s.length < 9) {
                s ~= "f";
            }
        } 
        string ss = "#";
        foreach (i; 1..9) {
            if ((s[i] >= '0' && s[i] <= '9') 
                || (s[i] >= 'A' && s[i] <= 'F') 
                || (s[i] >= 'a' && s[i] <= 'f')) {
                ss ~= s[i];
            } else {
                ss ~= "f";
            }
        }
        s = ss;
        // Color Code に変換し表示
        double r = s[1..3].strToDouble / 255.9999;
        double g = s[3..5].strToDouble / 255.9999;
        double b = s[5..7].strToDouble / 255.9999;
        // double a = s[7..9].strToDouble / 255.9999;
        double a = "ff".strToDouble / 255.9999;
        this.color(NSColor.colorRGB(r, g, b, a));
        string str = '#' ~ s[1..7] ~ "ff";
        codeField.attrStr = str.toAttrStr(null, NSColor.darkGray);
    }	
}

double strToDouble(string s) { // 16進数文字列をdoubleに変換する
    return (parse!(int)(s, 16)).to!double;
}

class ColorEncoder {
    void encode(ColorWell cw) {
        NSColor color = cw.color.spaceName(DeRGB.toNs); // NSColorSpaceName
        int r = cast(int)(color.redComponent   * 255.9999);
        int g = cast(int)(color.greenComponent * 255.9999);
        int b = cast(int)(color.blueComponent  * 255.9999);
        int a = cast(int)(color.alphaComponent * 255.9999);
        string fieldStr = format("#%02x%02x%02x%02x", r, g, b, a);
        NSFont font = NSFont.nameSize("Monaco".toNs, 20);
        codeField.attrStr = fieldStr.toAttrStr(font, NSColor.darkGray);
    }
}

extern (Objective-C) 
class Label : NSTextField {
    override static Label alloc() @selector("alloc");
    override Label init(NSRect) @selector("initWithFrame:");
    Label textVal(string labelStr, NSFont font) @selector("setValues:font:") {
        this.bgColor = NSColor.clear;
        this.bordered = false;
        this.editable = false;
        this.selectable = false;
        this.attrStr = labelStr.toAttrStr(font, NSColor.darkGray);
        return this;
    }
}               
cocoa/window.d
cocoa/control.d
cocoa/menus.d