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

NSComboBox を使ってみたい

NSComboBox、delegate を使ってみました。dataSource は使用せず、 D言語の配列を直接 ComboBox リストデータに読み込みました。

NSComboBox の Sample

サンプルコード

Powered by Prism

combobox/dub.json

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

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

string appName;
string versionNo = "0.0.3";
string helpMessage = "簡単なWindowをCocoaAPIを使用して、\nD言語で表示しています。";

DrawView dView;
ComboBox cbBox;
Label labelItem;
string sItem;
long sIndex;
ViewController vCtrler;

string[] items = [ "北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", 
 "福島県", "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県",
 "新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", "静岡県",
 "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県",
 "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", 
 "高知県", "福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", 
 "沖縄県" ];

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, 200);
    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;
    vCtrler = ViewController.alloc.init;
    dView = DrawView.alloc.init;
    vCtrler.view.subview = dView;
    win.contentView = dView;
    win.moveTop = NSPoint(200, 900);
    win.makeKeyAndOrderFront = null;
    NSApp.activateIgnoringOtherApps = true;
}

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

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

void setComboBoxData() {
    cbBox = ComboBox.alloc.init(NSMakeRect(50, 50, 80, 20));
    cbBox.setValues;
    Label label = Label.alloc.init(NSMakeRect(150, 50, 100, 20));
    label.setValues("項目数 " ~ cbBox.numberOfItems.to!string);
    Label label2 = Label.alloc.init(NSMakeRect(50, 100, 100, 20));
    label2.setValues("選択された項目");
    labelItem = Label.alloc.init(NSMakeRect(150, 100, 100, 20));
    cbBox.onSelectedCbItem; // 最初のデータ表示
}

extern (Objective-C) 
class ViewController : NSViewController, NSComboBoxDelegate {
    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 comboBoxSelectionDidChange(NSNotification) 
            @selector("comboBoxSelectionDidChange:") {
        // writeln("PopUp List の変更が完了した。");
        sItem = cbBox.selectedItem.toDs;
        sIndex = cbBox.indexItem + 1;
        labelItem.setValues(sItem ~ "  " ~ sIndex.to!string);
    }
   /*
    void comboBoxSelectionIsChanging(NSNotification)
            @selector("comboBoxSelectionIsChanging:") {
        // writeln("PopUp List の選択が変更されている。");
    }
    void comboBoxWillDismiss(NSNotification)
            @selector("comboBoxWillDismiss:") {
        // writeln("PopUp List が閉じられてる。");       
    }
    void comboBoxWillPopUp(NSNotification)
            @selector("comboBoxWillPopUp:") {
        // writeln("PopUp List が表示されている。");
    } 
   */
}

extern (Objective-C)
class ComboBox : NSComboBox {
    override static ComboBox alloc() @selector("alloc");
    override ComboBox init(NSRect) @selector("initWithFrame:");
    void setValues() @selector("setValues") {
        this.bordered = false;
        this.visibleItems = 10;
        this.completes = true;
        this.usesDataSource = false;
        this.delegate_ = vCtrler; 
        this.target = this;
        this.action = sel_registerName("onSelectedCbItem".toCs);
        foreach(i; 0 .. items.length) 
            this.addItem(items[i].toNs);
        this.selectItem = 6; // 初期表示Item
        dView.subview = this;
    }
    void onSelectedCbItem() @selector("onSelectedCbItem") {
        sItem = this.selectedItem.toDs;
        sIndex = this.indexItem + 1;
        if (sItem) 
            labelItem.setValues(sItem ~ "  " ~ sIndex.to!string);
        else 
            labelItem.setValues("選択できません。");
    } 
}

extern (Objective-C) 
class Label : NSTextField {
    override static Label alloc() @selector("alloc");
    override Label init(NSRect) @selector("initWithFrame:");
    void setValues(string str) @selector("setValues:") {
        this.str = str;
        this.bgColor = NSColor.clear;
        this.bordered = false;
        this.editable = false;
        this.selectable = false;
        dView.subview = this;
    }
}

extern (Objective-C)
extern class NSComboBox : NSTextField {
    override static NSComboBox alloc() @selector("alloc");
    // override NSComboBox init() @selector("init");
    override NSComboBox init(NSRect) @selector("initWithFrame:");
    void addItem(NSObject) @selector("addItemWithObjectValue:");
    void insert(NSObject, NSInteger) @selector("insertItemWithObjectValue:atIndex:");
    // CGFloat itemHeight() @selector("itemHeight"); // default 16.0
    NSInteger numberOfItems() @selector("numberOfItems");
    // NSInteger visibleItems() @selector("numberOfVisibleItems");
    NSInteger indexValue(NSObject) @selector("indexOfItemWithObjectValue:");
    NSObject itemValue(NSInteger) @selector("itemObjectValueAtIndex:");
    NSString itemValueS(NSInteger) @selector("itemObjectValueAtIndex:");
    NSString selectedItem() @selector("objectValueOfSelectedItem");
    void visibleItems(NSInteger) @selector("setNumberOfVisibleItems:");
    void selectItem(NSInteger) @selector("selectItemAtIndex:");
    NSInteger indexItem() @selector("indexOfSelectedItem");
    // void buttonBordered(bool) @selector("setButtonBordered:");
    // bool completes() @selector("completes");
    void completes(bool) @selector("setCompletes:");
    NSComboBox target(NSComboBox) @selector("setTarget:");
    override SEL action(SEL sel) @selector("setAction:");
    void delegate_(NSComboBoxDelegate) @selector("setDelegate:"); // 
    // void dataSource(NSComboBoxDataSource) @selector("setDataSource:"); //
    bool usesDataSource() @selector("usesDataSource");
    void usesDataSource(bool) @selector("setUsesDataSource:");
}

extern (Objective-C)
interface NSComboBoxDelegate {
    void comboBoxSelectionDidChange(NSNotification) 
        @selector("comboBoxSelectionDidChange:");
    @optional void comboBoxSelectionIsChanging(NSNotification)
        @selector("comboBoxSelectionIsChanging:");
    @optional void comboBoxWillDismiss(NSNotification)
        @selector("comboBoxWillDismiss:");
    @optional void comboBoxWillPopUp(NSNotification)
        @selector("comboBoxWillPopUp:");
}               
cocoa/window.d
cocoa/control.d
cocoa/menus.d