use crate::{arc, cg, define_obj_type, ns, objc};
#[doc(alias = "NSColorSystemEffect")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(isize)]
pub enum ColorSysEffect {
None,
Pressed,
DeepPressed,
Disabled,
Rollover,
}
define_obj_type!(
#[doc(alias = "NSColor")]
pub Color(ns::Id),
NS_COLOR
);
impl Color {
#[objc::msg_send(colorWithWhite:alpha:)]
pub fn with_white_alpha(white: cg::Float, alpha: cg::Float) -> arc::R<Self>;
#[objc::msg_send(colorWithRed:green:blue:alpha:)]
pub fn with_rgba(r: cg::Float, g: cg::Float, b: cg::Float, a: cg::Float) -> arc::R<Self>;
#[objc::msg_send(colorWithHue:saturation:brightness:alpha:)]
pub fn with_hsba(h: cg::Float, s: cg::Float, b: cg::Float, a: cg::Float) -> arc::R<Self>;
#[objc::msg_send(colorNamed:)]
pub fn color_named(name: &ns::String) -> Option<arc::R<Self>>;
pub fn named(name: impl AsRef<ns::String>) -> Option<arc::R<Self>> {
Self::color_named(name.as_ref())
}
#[objc::msg_send(whiteComponent)]
pub unsafe fn white_component_throws(&self) -> cg::Float;
pub fn white_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.white_component_throws() })
}
#[objc::msg_send(alphaComponent)]
pub fn alpha_component(&self) -> cg::Float;
#[objc::msg_send(redComponent)]
pub unsafe fn red_component_throws(&self) -> cg::Float;
#[objc::msg_send(greenComponent)]
pub unsafe fn green_component_throws(&self) -> cg::Float;
#[objc::msg_send(blueComponent)]
pub unsafe fn blue_component_throws(&self) -> cg::Float;
pub fn red_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.red_component_throws() })
}
pub fn green_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.green_component_throws() })
}
pub fn blue_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.blue_component_throws() })
}
#[objc::msg_send(hueComponent)]
pub unsafe fn hue_component_throws(&self) -> cg::Float;
#[objc::msg_send(saturationComponent)]
pub unsafe fn saturation_component_throws(&self) -> cg::Float;
#[objc::msg_send(brightnessComponent)]
pub unsafe fn brightness_component_throws(&self) -> cg::Float;
pub fn hue_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.hue_component_throws() })
}
pub fn saturation_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.saturation_component_throws() })
}
pub fn brightness_component<'ar>(&self) -> Result<cg::Float, &'ar ns::Exception> {
ns::try_catch(|| unsafe { self.brightness_component_throws() })
}
#[objc::msg_send(colorSpace)]
pub unsafe fn color_space_throws(&self) -> arc::R<ns::ColorSpace>;
pub fn color_space<'ear>(&self) -> ns::ExResult<'ear, arc::R<ns::ColorSpace>> {
ns::try_catch(|| unsafe { self.color_space_throws() })
}
#[objc::msg_send(colorWithRed:green:blue:alpha:exposure:)]
#[objc::available(macos = 26.0)]
pub fn with_exposure(
r: cg::Float,
g: cg::Float,
b: cg::Float,
a: cg::Float,
exposure: cg::Float,
) -> arc::R<Self>;
#[objc::msg_send(colorWithRed:green:blue:alpha:linearExposure:)]
#[objc::available(macos = 26.0)]
pub fn with_linear_exposure(
r: cg::Float,
g: cg::Float,
b: cg::Float,
a: cg::Float,
exposure: cg::Float,
) -> arc::R<Self>;
#[objc::msg_send(colorByApplyingContentHeadroom:)]
#[objc::available(macos = 26.0)]
pub fn applying_content_headroom(&self, content_headroom: cg::Float) -> arc::R<Self>;
#[objc::msg_send(linearExposure)]
#[objc::available(macos = 26.0)]
pub fn linear_exposure(&self) -> cg::Float;
#[objc::msg_send(standardDynamicRangeColor)]
#[objc::available(macos = 26.0)]
pub fn sdr(&self) -> arc::R<Self>;
#[cfg(feature = "cg")]
#[objc::msg_send(CGColor)]
pub fn cg_color(&self) -> Option<&crate::cg::Color>;
}
impl Color {
#[objc::msg_send(blackColor)]
pub fn black() -> arc::R<Self>;
#[objc::msg_send(darkGrayColor)]
pub fn dark_gray() -> arc::R<Self>;
#[objc::msg_send(lightGrayColor)]
pub fn light_gray() -> arc::R<Self>;
#[objc::msg_send(whiteColor)]
pub fn white() -> arc::R<Self>;
#[objc::msg_send(grayColor)]
pub fn gray() -> arc::R<Self>;
#[objc::msg_send(redColor)]
pub fn red() -> arc::R<Self>;
#[objc::msg_send(greenColor)]
pub fn green() -> arc::R<Self>;
#[objc::msg_send(blueColor)]
pub fn blue() -> arc::R<Self>;
#[objc::msg_send(cyanColor)]
pub fn cyan() -> arc::R<Self>;
#[objc::msg_send(yellowColor)]
pub fn yellow() -> arc::R<Self>;
#[objc::msg_send(magentaColor)]
pub fn magenta() -> arc::R<Self>;
#[objc::msg_send(orangeColor)]
pub fn orange() -> arc::R<Self>;
#[objc::msg_send(purpleColor)]
pub fn purple() -> arc::R<Self>;
#[objc::msg_send(brownColor)]
pub fn brown() -> arc::R<Self>;
#[objc::msg_send(clearColor)]
pub fn clear() -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(labelColor)]
pub fn label() -> arc::R<Self>;
#[objc::msg_send(secondaryLabelColor)]
pub fn secondary_label() -> arc::R<Self>;
#[objc::msg_send(tertiaryLabelColor)]
pub fn tertiary_label() -> arc::R<Self>;
#[objc::msg_send(quaternaryLabelColor)]
pub fn quaternary_label() -> arc::R<Self>;
#[objc::msg_send(quinaryLabelColor)]
pub fn quinary_label() -> arc::R<Self>;
#[objc::msg_send(linkColor)]
pub fn link() -> arc::R<Self>;
#[objc::msg_send(placeholderTextColor)]
pub fn placeholder_text() -> arc::R<Self>;
#[objc::msg_send(windowFrameTextColor)]
pub fn window_frame_text() -> arc::R<Self>;
#[objc::msg_send(selectedMenuItemTextColor)]
pub fn selected_menu_item_text() -> arc::R<Self>;
#[objc::msg_send(alternateSelectedControlTextColor)]
pub fn alternate_selected_control_text() -> arc::R<Self>;
#[objc::msg_send(headerTextColor)]
pub fn header_text() -> arc::R<Self>;
#[objc::msg_send(separatorColor)]
pub fn separator() -> arc::R<Self>;
#[objc::msg_send(gridColor)]
pub fn grid() -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(windowBackgroundColor)]
pub fn window_bg() -> arc::R<Self>;
#[objc::msg_send(underPageBackgroundColor)]
pub fn under_page_bg() -> arc::R<Self>;
#[objc::msg_send(controlBackgroundColor)]
pub fn control_bg() -> arc::R<Self>;
#[objc::msg_send(selectedContentBackgroundColor)]
pub fn selected_content_bg() -> arc::R<Self>;
#[objc::msg_send(unemphasizedSelectedContentBackgroundColor)]
pub fn unemphasized_selected_content_bg() -> arc::R<Self>;
#[objc::msg_send(alternatingContentBackgroundColors)]
pub fn alternating_content_bg_colors() -> arc::R<ns::Array<Self>>;
}
impl Color {
#[objc::msg_send(textColor)]
pub fn text() -> arc::R<Self>;
#[objc::msg_send(textBackgroundColor)]
pub fn text_bg() -> arc::R<Self>;
#[objc::msg_send(textInsertionPointColor)]
pub fn text_insertion_point() -> arc::R<Self>;
#[objc::msg_send(selectedTextColor)]
pub fn selected_text() -> arc::R<Self>;
#[objc::msg_send(selectedTextBackgroundColor)]
pub fn selected_text_bg() -> arc::R<Self>;
#[objc::msg_send(unemphasizedSelectedTextBackgroundColor)]
pub fn unemphasized_selected_text_bg() -> arc::R<Self>;
#[objc::msg_send(unemphasizedSelectedTextColor)]
pub fn unemphasized_selected_text() -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(controlColor)]
pub fn control() -> arc::R<Self>;
#[objc::msg_send(controlTextColor)]
pub fn control_text() -> arc::R<Self>;
#[objc::msg_send(selectedControlColor)]
pub fn selected_control() -> arc::R<Self>;
#[objc::msg_send(selectedControlTextColor)]
pub fn selected_control_text() -> arc::R<Self>;
#[objc::msg_send(disabledControlTextColor)]
pub fn disabled_control_text() -> arc::R<Self>;
#[objc::msg_send(keyboardFocusIndicatorColor)]
pub fn keyboard_focus_indicator() -> arc::R<Self>;
#[objc::msg_send(scrubberTexturedBackgroundColor)]
pub fn scrubber_textured_bg() -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(systemRedColor)]
pub fn sys_red() -> arc::R<Self>;
#[objc::msg_send(systemGreenColor)]
pub fn sys_green() -> arc::R<Self>;
#[objc::msg_send(systemBlueColor)]
pub fn sys_blue() -> arc::R<Self>;
#[objc::msg_send(systemOrangeColor)]
pub fn sys_orange() -> arc::R<Self>;
#[objc::msg_send(systemYellowColor)]
pub fn sys_yellow() -> arc::R<Self>;
#[objc::msg_send(systemBrownColor)]
pub fn sys_brown() -> arc::R<Self>;
#[objc::msg_send(systemPinkColor)]
pub fn sys_pink() -> arc::R<Self>;
#[objc::msg_send(systemPurpleColor)]
pub fn sys_purple() -> arc::R<Self>;
#[objc::msg_send(systemGrayColor)]
pub fn sys_gray() -> arc::R<Self>;
#[objc::msg_send(systemTealColor)]
pub fn sys_teal() -> arc::R<Self>;
#[objc::msg_send(systemIndigoColor)]
pub fn sys_indigo() -> arc::R<Self>;
#[objc::msg_send(systemMintColor)]
pub fn sys_mint() -> arc::R<Self>;
#[objc::msg_send(systemCyanColor)]
pub fn sys_cyan() -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(systemFillColor)]
pub fn sys_fill() -> arc::R<Self>;
#[objc::msg_send(secondarySystemFillColor)]
pub fn sys_secondary_fill() -> arc::R<Self>;
#[objc::msg_send(tertiarySystemFillColor)]
pub fn sys_tertiary_fill() -> arc::R<Self>;
#[objc::msg_send(quaternarySystemFillColor)]
pub fn sys_quaternary_fill() -> arc::R<Self>;
#[objc::msg_send(quinarySystemFillColor)]
pub fn sys_quinary_fill() -> arc::R<Self>;
#[objc::msg_send(controlAccentColor)]
pub fn control_accent() -> arc::R<Self>;
#[objc::msg_send(currentControlTint)]
pub fn current_control_tint() -> ns::ControlTint;
#[objc::msg_send(highlightColor)]
pub fn highlight() -> arc::R<Self>;
#[objc::msg_send(shadowColor)]
pub fn shadow() -> arc::R<Self>;
#[objc::msg_send(highlightWithLevel:)]
pub fn highlight_with_level(&self, val: cg::Float) -> Option<arc::R<Self>>;
#[objc::msg_send(shadowWithLevel:)]
pub fn shadow_with_level(&self, val: cg::Float) -> Option<arc::R<Self>>;
#[objc::msg_send(colorWithSystemEffect:)]
pub fn color_with_sys_effect(&self, sys_effect: ns::ColorSysEffect) -> arc::R<Self>;
}
impl Color {
#[objc::msg_send(set)]
pub fn set(&self);
#[objc::msg_send(setFill)]
pub fn set_fill(&self);
#[objc::msg_send(setStroke)]
pub fn set_stroke(&self);
}
impl Color {
#[objc::msg_send(blendedColorWithFraction:ofColor:)]
pub fn blended_color_with_fraction(
&self,
fraction: cg::Float,
of_color: &Self,
) -> Option<arc::R<Self>>;
}
unsafe impl Send for Color {}
#[link(name = "app", kind = "static")]
unsafe extern "C" {
static NS_COLOR: &'static objc::Class<Color>;
}
#[cfg(test)]
mod tests {
use crate::{api, ns};
#[test]
fn basics() {
let black = ns::Color::with_white_alpha(0.0, 1.0);
assert_eq!(black.white_component().unwrap(), 0.0);
assert_eq!(black.alpha_component(), 1.0);
black.red_component().expect_err("should be err");
assert!(ns::Color::named(ns::str!(c"foo")).is_none());
}
#[test]
fn hsb_components() {
let color = ns::Color::with_hsba(0.5, 0.75, 0.25, 1.0);
assert!((color.hue_component().unwrap() - 0.5f64).abs() < f64::EPSILON);
assert!((color.saturation_component().unwrap() - 0.75).abs() < f64::EPSILON);
assert!((color.brightness_component().unwrap() - 0.25).abs() < f64::EPSILON);
let gray = ns::Color::with_white_alpha(0.5, 1.0);
gray.hue_component()
.expect_err("gray color shouldn't have hue component");
}
#[test]
fn hdr() {
let red = ns::Color::sys_red();
if api::macos_available("26.0") {
unsafe {
let bright_red = red.applying_content_headroom(2.0);
assert_eq!(bright_red.linear_exposure(), 1.0);
assert!(bright_red.color_space().is_err());
let bright_red = ns::Color::with_linear_exposure(1.0, 0.0, 0.0, 1.0, 2.0);
assert_eq!(bright_red.linear_exposure(), 2.0);
assert!(bright_red.color_space().is_ok());
let red = bright_red.sdr();
assert_eq!(red.linear_exposure(), 1.0);
}
}
}
}