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