1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use cocoa::base::{id, nil, selector, NO};

use cocoa::appkit::{
    NSApp, NSApplication, NSApplicationActivateIgnoringOtherApps,
    NSApplicationActivationPolicyRegular, NSBackingStoreType, NSColor, NSColorSpace, NSMenu,
    NSMenuItem, NSRunningApplication, NSWindow, NSWindowStyleMask,
};
use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSProcessInfo, NSRect, NSSize, NSString};

fn main() {
    unsafe {
        // Create the app.
        let app = create_app();

        // Create some colors
        let clear = NSColor::clearColor(nil);
        let black = NSColor::colorWithRed_green_blue_alpha_(nil, 0.0, 0.0, 0.0, 1.0);
        let srgb_red = NSColor::colorWithSRGBRed_green_blue_alpha_(nil, 1.0, 0.0, 0.0, 1.0);
        let device_green = NSColor::colorWithDeviceRed_green_blue_alpha_(nil, 0.0, 1.0, 0.0, 1.0);
        let display_p3_blue =
            NSColor::colorWithDisplayP3Red_green_blue_alpha_(nil, 0.0, 0.0, 1.0, 1.0);
        let calibrated_cyan =
            NSColor::colorWithCalibratedRed_green_blue_alpha_(nil, 0.0, 1.0, 1.0, 1.0);

        // Create windows with different color types.
        let _win_clear = create_window(NSString::alloc(nil).init_str("clear"), clear);
        let _win_black = create_window(NSString::alloc(nil).init_str("black"), black);
        let _win_srgb_red = create_window(NSString::alloc(nil).init_str("srgb_red"), srgb_red);
        let _win_device_green =
            create_window(NSString::alloc(nil).init_str("device_green"), device_green);
        let _win_display_p3_blue = create_window(
            NSString::alloc(nil).init_str("display_p3_blue"),
            display_p3_blue,
        );
        let _win_calibrated_cyan = create_window(
            NSString::alloc(nil).init_str("calibrated_cyan"),
            calibrated_cyan,
        );

        // Extract component values from a color.
        // NOTE: some components will raise an exception if the color is not
        // in the correct NSColorSpace. Refer to Apple's documentation for details.
        // https://developer.apple.com/documentation/appkit/nscolor?language=objc
        let my_color = NSColor::colorWithRed_green_blue_alpha_(nil, 0.25, 0.75, 0.5, 0.25);
        println!("alphaComponent: {:?}", my_color.alphaComponent());
        println!("redComponent: {:?}", my_color.redComponent());
        println!("greenComponent: {:?}", my_color.greenComponent());
        println!("blueComponent: {:?}", my_color.blueComponent());
        println!("hueComponent: {:?}", my_color.hueComponent());
        println!("saturationComponent: {:?}", my_color.saturationComponent());
        println!("brightnessComponent: {:?}", my_color.brightnessComponent());

        // Changing color spaces.
        let my_color_cmyk_cs =
            my_color.colorUsingColorSpace_(NSColorSpace::deviceCMYKColorSpace(nil));
        println!("blackComponent: {:?}", my_color_cmyk_cs.blackComponent());
        println!("cyanComponent: {:?}", my_color_cmyk_cs.cyanComponent());
        println!(
            "magentaComponent: {:?}",
            my_color_cmyk_cs.magentaComponent()
        );
        println!("yellowComponent: {:?}", my_color_cmyk_cs.yellowComponent());

        // Getting NSColorSpace name.
        let cs = NSColorSpace::genericGamma22GrayColorSpace(nil);
        let cs_name = cs.localizedName();
        let cs_name_bytes = cs_name.UTF8String() as *const u8;
        let cs_name_string =
            std::str::from_utf8(std::slice::from_raw_parts(cs_name_bytes, cs_name.len())).unwrap();
        println!("NSColorSpace: {:?}", cs_name_string);

        // Creating an NSColorSpace from CGColorSpaceRef.
        let cg_cs = cs.CGColorSpace();
        let cs = NSColorSpace::alloc(nil).initWithCGColorSpace_(cg_cs);
        let cs_name = cs.localizedName();
        let cs_name_bytes = cs_name.UTF8String() as *const u8;
        let cs_name_string =
            std::str::from_utf8(std::slice::from_raw_parts(cs_name_bytes, cs_name.len())).unwrap();
        println!("initWithCGColorSpace_: {:?}", cs_name_string);

        app.run();
    }
}

unsafe fn create_window(title: id, color: id) -> id {
    let window = NSWindow::alloc(nil)
        .initWithContentRect_styleMask_backing_defer_(
            NSRect::new(NSPoint::new(0., 0.), NSSize::new(200., 200.)),
            NSWindowStyleMask::NSTitledWindowMask
                | NSWindowStyleMask::NSClosableWindowMask
                | NSWindowStyleMask::NSResizableWindowMask
                | NSWindowStyleMask::NSMiniaturizableWindowMask
                | NSWindowStyleMask::NSUnifiedTitleAndToolbarWindowMask,
            NSBackingStoreType::NSBackingStoreBuffered,
            NO,
        )
        .autorelease();

    window.cascadeTopLeftFromPoint_(NSPoint::new(20., 20.));
    window.setTitle_(title);
    window.setBackgroundColor_(color);
    window.makeKeyAndOrderFront_(nil);
    window
}

unsafe fn create_app() -> id {
    let _pool = NSAutoreleasePool::new(nil);

    let app = NSApp();
    app.setActivationPolicy_(NSApplicationActivationPolicyRegular);

    // create Menu Bar
    let menubar = NSMenu::new(nil).autorelease();
    let app_menu_item = NSMenuItem::new(nil).autorelease();
    menubar.addItem_(app_menu_item);
    app.setMainMenu_(menubar);

    // create Application menu
    let app_menu = NSMenu::new(nil).autorelease();
    let quit_prefix = NSString::alloc(nil).init_str("Quit ");
    let quit_title =
        quit_prefix.stringByAppendingString_(NSProcessInfo::processInfo(nil).processName());
    let quit_action = selector("terminate:");
    let quit_key = NSString::alloc(nil).init_str("q");
    let quit_item = NSMenuItem::alloc(nil)
        .initWithTitle_action_keyEquivalent_(quit_title, quit_action, quit_key)
        .autorelease();
    app_menu.addItem_(quit_item);
    app_menu_item.setSubmenu_(app_menu);

    let current_app = NSRunningApplication::currentApplication(nil);
    current_app.activateWithOptions_(NSApplicationActivateIgnoringOtherApps);

    app
}