1use azul_core::{
4 callbacks::{CoreCallbackData, Update},
5 dom::Dom,
6 refany::RefAny,
7};
8use azul_css::dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec};
9use azul_css::{
10 props::{
11 basic::*,
12 layout::*,
13 property::{CssProperty, *},
14 style::*,
15 },
16 *,
17};
18
19use crate::callbacks::{Callback, CallbackInfo};
20
21#[derive(Debug, Default, Clone, PartialEq)]
22#[repr(C)]
23pub struct ColorInput {
24 pub color_input_state: ColorInputStateWrapper,
25 pub style: CssPropertyWithConditionsVec,
26}
27
28pub type ColorInputOnValueChangeCallbackType =
29 extern "C" fn(RefAny, CallbackInfo, ColorInputState) -> Update;
30impl_widget_callback!(
31 ColorInputOnValueChange,
32 OptionColorInputOnValueChange,
33 ColorInputOnValueChangeCallback,
34 ColorInputOnValueChangeCallbackType
35);
36
37#[derive(Debug, Clone, PartialEq, PartialOrd)]
38#[repr(C)]
39pub struct ColorInputStateWrapper {
40 pub inner: ColorInputState,
41 pub title: AzString,
42 pub on_value_change: OptionColorInputOnValueChange,
43}
44
45impl Default for ColorInputStateWrapper {
46 fn default() -> Self {
47 Self {
48 inner: ColorInputState::default(),
49 title: AzString::from_const_str("Pick color"),
50 on_value_change: None.into(),
51 }
52 }
53}
54
55#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
56#[repr(C)]
57pub struct ColorInputState {
58 pub color: ColorU,
59}
60
61impl Default for ColorInputState {
62 fn default() -> Self {
63 Self {
64 color: ColorU {
65 r: 255,
66 g: 255,
67 b: 255,
68 a: 255,
69 },
70 }
71 }
72}
73
74static DEFAULT_COLOR_INPUT_STYLE: &[CssPropertyWithConditions] = &[
75 CssPropertyWithConditions::simple(CssProperty::const_display(LayoutDisplay::Block)),
76 CssPropertyWithConditions::simple(CssProperty::const_flex_grow(LayoutFlexGrow::const_new(0))),
77 CssPropertyWithConditions::simple(CssProperty::const_width(LayoutWidth::const_px(14))),
78 CssPropertyWithConditions::simple(CssProperty::const_height(LayoutHeight::const_px(14))),
79 CssPropertyWithConditions::simple(CssProperty::const_cursor(StyleCursor::Pointer)),
80];
81
82impl ColorInput {
83 #[inline]
84 pub fn create(color: ColorU) -> Self {
85 Self {
86 color_input_state: ColorInputStateWrapper {
87 inner: ColorInputState {
88 color,
89 ..Default::default()
90 },
91 ..Default::default()
92 },
93 style: CssPropertyWithConditionsVec::from_const_slice(DEFAULT_COLOR_INPUT_STYLE),
94 }
95 }
96
97 #[inline]
98 pub fn set_on_value_change<I: Into<ColorInputOnValueChangeCallback>>(
99 &mut self,
100 data: RefAny,
101 callback: I,
102 ) {
103 self.color_input_state.on_value_change = Some(ColorInputOnValueChange {
104 callback: callback.into(),
105 refany: data,
106 })
107 .into();
108 }
109
110 #[inline]
111 pub fn with_on_value_change<C: Into<ColorInputOnValueChangeCallback>>(
112 mut self,
113 data: RefAny,
114 callback: C,
115 ) -> Self {
116 self.set_on_value_change(data, callback);
117 self
118 }
119
120 #[inline]
121 pub fn swap_with_default(&mut self) -> Self {
122 let mut s = Self::default();
123 core::mem::swap(&mut s, self);
124 s
125 }
126
127 #[inline]
128 pub fn dom(self) -> Dom {
129 use azul_core::{
130 callbacks::{CoreCallback, CoreCallbackData},
131 dom::{EventFilter, HoverEventFilter, IdOrClass::Class},
132 };
133
134 let mut style = self.style.into_library_owned_vec();
135 style.push(CssPropertyWithConditions::simple(
136 CssProperty::const_background_content(
137 vec![StyleBackgroundContent::Color(
138 self.color_input_state.inner.color,
139 )]
140 .into(),
141 ),
142 ));
143
144 Dom::create_div()
145 .with_ids_and_classes(vec![Class("__azul_native_color_input".into())].into())
146 .with_css_props(style.into())
147 .with_callbacks(
148 vec![CoreCallbackData {
149 event: EventFilter::Hover(HoverEventFilter::MouseUp),
150 refany: RefAny::new(self.color_input_state),
151 callback: CoreCallback {
152 cb: on_color_input_clicked as usize,
153 ctx: azul_core::refany::OptionRefAny::None,
154 },
155 }]
156 .into(),
157 )
158 }
159}
160
161extern "C" fn on_color_input_clicked(mut data: RefAny, mut info: CallbackInfo) -> Update {
162 let mut color_input = match data.downcast_mut::<ColorInputStateWrapper>() {
163 Some(s) => s,
164 None => return Update::DoNothing,
165 };
166
167 let result = {
171 let color_input = &mut *color_input;
172 let onvaluechange = &mut color_input.on_value_change;
173 let inner = color_input.inner.clone();
174
175 match onvaluechange.as_mut() {
176 Some(ColorInputOnValueChange {
177 callback,
178 refany: data,
179 }) => (callback.cb)(data.clone(), info.clone(), inner),
180 None => Update::DoNothing,
181 }
182 };
183
184 result
185}