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