1use style::color::AbsoluteColor;
14use style::properties::PropertyDeclaration;
15use style::values::specified::box_::{Display, PositionProperty};
16use style::values::specified::{
17 Color, FontSize, FontWeight, Margin, NonNegativeLengthPercentage, Opacity, Size,
18};
19
20use crate::dom::document_cell::DocumentCell;
21use crate::id::RawId;
22
23pub struct StyleAccess {
29 cell: DocumentCell,
30 id: RawId,
31 pending: Vec<PropertyDeclaration>,
32}
33
34impl StyleAccess {
35 pub(crate) fn new(cell: DocumentCell, id: RawId) -> Self {
36 Self {
37 cell,
38 id,
39 pending: Vec::new(),
40 }
41 }
42
43 pub fn display(&mut self, value: Display) -> &mut Self {
46 self.pending.push(PropertyDeclaration::Display(value));
47 self
48 }
49
50 pub fn color(&mut self, value: impl Into<AbsoluteColor>) -> &mut Self {
53 use style::values::specified::color::ColorPropertyValue;
54 self.pending
55 .push(PropertyDeclaration::Color(ColorPropertyValue(
56 Color::from_absolute_color(value.into()),
57 )));
58 self
59 }
60
61 pub fn background_color(&mut self, value: impl Into<AbsoluteColor>) -> &mut Self {
62 self.pending.push(PropertyDeclaration::BackgroundColor(
63 Color::from_absolute_color(value.into()),
64 ));
65 self
66 }
67
68 pub fn width(&mut self, value: impl Into<Size>) -> &mut Self {
71 self.pending.push(PropertyDeclaration::Width(value.into()));
72 self
73 }
74
75 pub fn height(&mut self, value: impl Into<Size>) -> &mut Self {
76 self.pending.push(PropertyDeclaration::Height(value.into()));
77 self
78 }
79
80 pub fn min_width(&mut self, value: impl Into<Size>) -> &mut Self {
81 self.pending
82 .push(PropertyDeclaration::MinWidth(value.into()));
83 self
84 }
85
86 pub fn min_height(&mut self, value: impl Into<Size>) -> &mut Self {
87 self.pending
88 .push(PropertyDeclaration::MinHeight(value.into()));
89 self
90 }
91
92 pub fn margin_top(&mut self, value: impl Into<Margin>) -> &mut Self {
95 self.pending
96 .push(PropertyDeclaration::MarginTop(value.into()));
97 self
98 }
99
100 pub fn margin_right(&mut self, value: impl Into<Margin>) -> &mut Self {
101 self.pending
102 .push(PropertyDeclaration::MarginRight(value.into()));
103 self
104 }
105
106 pub fn margin_bottom(&mut self, value: impl Into<Margin>) -> &mut Self {
107 self.pending
108 .push(PropertyDeclaration::MarginBottom(value.into()));
109 self
110 }
111
112 pub fn margin_left(&mut self, value: impl Into<Margin>) -> &mut Self {
113 self.pending
114 .push(PropertyDeclaration::MarginLeft(value.into()));
115 self
116 }
117
118 pub fn margin(&mut self, value: impl Into<Margin>) -> &mut Self {
119 let v = value.into();
120 self.pending.push(PropertyDeclaration::MarginTop(v.clone()));
121 self.pending
122 .push(PropertyDeclaration::MarginRight(v.clone()));
123 self.pending
124 .push(PropertyDeclaration::MarginBottom(v.clone()));
125 self.pending.push(PropertyDeclaration::MarginLeft(v));
126 self
127 }
128
129 pub fn padding_top(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
132 self.pending
133 .push(PropertyDeclaration::PaddingTop(value.into()));
134 self
135 }
136
137 pub fn padding_right(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
138 self.pending
139 .push(PropertyDeclaration::PaddingRight(value.into()));
140 self
141 }
142
143 pub fn padding_bottom(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
144 self.pending
145 .push(PropertyDeclaration::PaddingBottom(value.into()));
146 self
147 }
148
149 pub fn padding_left(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
150 self.pending
151 .push(PropertyDeclaration::PaddingLeft(value.into()));
152 self
153 }
154
155 pub fn padding(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
156 let v = value.into();
157 self.pending
158 .push(PropertyDeclaration::PaddingTop(v.clone()));
159 self.pending
160 .push(PropertyDeclaration::PaddingRight(v.clone()));
161 self.pending
162 .push(PropertyDeclaration::PaddingBottom(v.clone()));
163 self.pending.push(PropertyDeclaration::PaddingLeft(v));
164 self
165 }
166
167 pub fn position(&mut self, value: PositionProperty) -> &mut Self {
170 self.pending.push(PropertyDeclaration::Position(value));
171 self
172 }
173
174 pub fn font_size(&mut self, value: FontSize) -> &mut Self {
177 self.pending.push(PropertyDeclaration::FontSize(value));
178 self
179 }
180
181 pub fn font_weight(&mut self, value: FontWeight) -> &mut Self {
182 self.pending.push(PropertyDeclaration::FontWeight(value));
183 self
184 }
185
186 pub fn font_family(&mut self, name: &str) -> &mut Self {
193 use style::Atom;
194 use style::values::computed::font::{
195 FamilyName, FontFamilyList, FontFamilyNameSyntax, SingleFontFamily,
196 };
197 use style::values::specified::font::FontFamily;
198
199 let list = FontFamilyList {
200 list: style::ArcSlice::from_iter(std::iter::once(SingleFontFamily::FamilyName(
201 FamilyName {
202 name: Atom::from(name),
203 syntax: FontFamilyNameSyntax::Quoted,
204 },
205 ))),
206 };
207 self.pending
208 .push(PropertyDeclaration::FontFamily(FontFamily::Values(list)));
209 self
210 }
211
212 pub fn opacity(&mut self, value: Opacity) -> &mut Self {
215 self.pending.push(PropertyDeclaration::Opacity(value));
216 self
217 }
218
219 pub fn flex_grow(&mut self, value: f32) -> &mut Self {
222 use style::values::generics::NonNegative;
223 use style::values::specified::Number;
224 self.pending
225 .push(PropertyDeclaration::FlexGrow(NonNegative(Number::new(
226 value,
227 ))));
228 self
229 }
230
231 pub fn flex_shrink(&mut self, value: f32) -> &mut Self {
232 use style::values::generics::NonNegative;
233 use style::values::specified::Number;
234 self.pending
235 .push(PropertyDeclaration::FlexShrink(NonNegative(Number::new(
236 value,
237 ))));
238 self
239 }
240
241 pub fn flex_basis(&mut self, value: impl Into<Size>) -> &mut Self {
242 use style::values::generics::flex::GenericFlexBasis;
243 use style::values::generics::length::GenericSize;
244 let size = value.into();
245 let basis = match size {
246 GenericSize::Auto => GenericFlexBasis::Content,
247 other => GenericFlexBasis::Size(other),
248 };
249 self.pending
250 .push(PropertyDeclaration::FlexBasis(Box::new(basis)));
251 self
252 }
253
254 pub fn gap(&mut self, value: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
257 use style::values::generics::length::GenericLengthPercentageOrNormal;
258 let v: NonNegativeLengthPercentage = value.into();
259 self.pending.push(PropertyDeclaration::RowGap(
260 GenericLengthPercentageOrNormal::LengthPercentage(v.clone()),
261 ));
262 self.pending.push(PropertyDeclaration::ColumnGap(
263 GenericLengthPercentageOrNormal::LengthPercentage(v),
264 ));
265 self
266 }
267
268 pub fn flex_direction(
271 &mut self,
272 value: style::computed_values::flex_direction::T,
273 ) -> &mut Self {
274 self.pending.push(PropertyDeclaration::FlexDirection(value));
275 self
276 }
277
278 pub fn flex_wrap(&mut self, value: style::computed_values::flex_wrap::T) -> &mut Self {
279 self.pending.push(PropertyDeclaration::FlexWrap(value));
280 self
281 }
282
283 pub fn flex_row(&mut self) -> &mut Self {
285 self.display(Display::Flex);
286 self.flex_direction(style::computed_values::flex_direction::T::Row)
287 }
288
289 pub fn flex_col(&mut self) -> &mut Self {
291 self.display(Display::Flex);
292 self.flex_direction(style::computed_values::flex_direction::T::Column)
293 }
294
295 pub fn align_items_center(&mut self) -> &mut Self {
298 use style::values::specified::align::{AlignFlags, ItemPlacement};
299 self.pending
300 .push(PropertyDeclaration::AlignItems(ItemPlacement(
301 AlignFlags::CENTER,
302 )));
303 self
304 }
305 pub fn align_items_start(&mut self) -> &mut Self {
306 use style::values::specified::align::{AlignFlags, ItemPlacement};
307 self.pending
308 .push(PropertyDeclaration::AlignItems(ItemPlacement(
309 AlignFlags::FLEX_START,
310 )));
311 self
312 }
313 pub fn align_items_end(&mut self) -> &mut Self {
314 use style::values::specified::align::{AlignFlags, ItemPlacement};
315 self.pending
316 .push(PropertyDeclaration::AlignItems(ItemPlacement(
317 AlignFlags::FLEX_END,
318 )));
319 self
320 }
321 pub fn align_items_stretch(&mut self) -> &mut Self {
322 use style::values::specified::align::{AlignFlags, ItemPlacement};
323 self.pending
324 .push(PropertyDeclaration::AlignItems(ItemPlacement(
325 AlignFlags::STRETCH,
326 )));
327 self
328 }
329
330 pub fn justify_content_center(&mut self) -> &mut Self {
331 use style::values::specified::align::{AlignFlags, ContentDistribution};
332 self.pending.push(PropertyDeclaration::JustifyContent(
333 ContentDistribution::new(AlignFlags::CENTER),
334 ));
335 self
336 }
337 pub fn justify_content_start(&mut self) -> &mut Self {
338 use style::values::specified::align::{AlignFlags, ContentDistribution};
339 self.pending.push(PropertyDeclaration::JustifyContent(
340 ContentDistribution::new(AlignFlags::FLEX_START),
341 ));
342 self
343 }
344 pub fn justify_content_end(&mut self) -> &mut Self {
345 use style::values::specified::align::{AlignFlags, ContentDistribution};
346 self.pending.push(PropertyDeclaration::JustifyContent(
347 ContentDistribution::new(AlignFlags::FLEX_END),
348 ));
349 self
350 }
351 pub fn justify_content_between(&mut self) -> &mut Self {
352 use style::values::specified::align::{AlignFlags, ContentDistribution};
353 self.pending.push(PropertyDeclaration::JustifyContent(
354 ContentDistribution::new(AlignFlags::SPACE_BETWEEN),
355 ));
356 self
357 }
358
359 pub fn border_radius(
362 &mut self,
363 v: impl Into<NonNegativeLengthPercentage> + Clone,
364 ) -> &mut Self {
365 use style::values::generics::border::GenericBorderCornerRadius;
366 use style::values::generics::size::Size2D;
367 let lp = v.into();
368 let r = GenericBorderCornerRadius(Size2D::new(lp.clone(), lp));
369 self.pending
370 .push(PropertyDeclaration::BorderTopLeftRadius(Box::new(
371 r.clone(),
372 )));
373 self.pending
374 .push(PropertyDeclaration::BorderTopRightRadius(Box::new(
375 r.clone(),
376 )));
377 self.pending
378 .push(PropertyDeclaration::BorderBottomRightRadius(Box::new(
379 r.clone(),
380 )));
381 self.pending
382 .push(PropertyDeclaration::BorderBottomLeftRadius(Box::new(r)));
383 self
384 }
385
386 pub fn border_width(&mut self, v: impl Into<NonNegativeLengthPercentage> + Clone) -> &mut Self {
387 let lp = v.into();
391 self.pending.push(PropertyDeclaration::BorderTopWidth(
393 style::values::specified::BorderSideWidth::from_px(self.extract_px(&lp)),
394 ));
395 self.pending.push(PropertyDeclaration::BorderRightWidth(
396 style::values::specified::BorderSideWidth::from_px(self.extract_px(&lp)),
397 ));
398 self.pending.push(PropertyDeclaration::BorderBottomWidth(
399 style::values::specified::BorderSideWidth::from_px(self.extract_px(&lp)),
400 ));
401 self.pending.push(PropertyDeclaration::BorderLeftWidth(
402 style::values::specified::BorderSideWidth::from_px(self.extract_px(&lp)),
403 ));
404 self
405 }
406
407 pub fn border_style(&mut self, v: style::values::specified::border::BorderStyle) -> &mut Self {
408 self.pending.push(PropertyDeclaration::BorderTopStyle(v));
409 self.pending.push(PropertyDeclaration::BorderRightStyle(v));
410 self.pending.push(PropertyDeclaration::BorderBottomStyle(v));
411 self.pending.push(PropertyDeclaration::BorderLeftStyle(v));
412 self
413 }
414
415 pub fn border_color(&mut self, v: impl Into<AbsoluteColor>) -> &mut Self {
416 let c = Color::from_absolute_color(v.into());
417 self.pending
418 .push(PropertyDeclaration::BorderTopColor(c.clone()));
419 self.pending
420 .push(PropertyDeclaration::BorderRightColor(c.clone()));
421 self.pending
422 .push(PropertyDeclaration::BorderBottomColor(c.clone()));
423 self.pending.push(PropertyDeclaration::BorderLeftColor(c));
424 self
425 }
426
427 pub fn border_bottom_width_px(&mut self, v: f32) -> &mut Self {
428 self.pending.push(PropertyDeclaration::BorderBottomWidth(
429 style::values::specified::BorderSideWidth::from_px(v),
430 ));
431 self
432 }
433
434 pub fn border_bottom_style(
435 &mut self,
436 v: style::values::specified::border::BorderStyle,
437 ) -> &mut Self {
438 self.pending.push(PropertyDeclaration::BorderBottomStyle(v));
439 self
440 }
441
442 pub fn border_bottom_color(&mut self, v: impl Into<AbsoluteColor>) -> &mut Self {
443 self.pending.push(PropertyDeclaration::BorderBottomColor(
444 Color::from_absolute_color(v.into()),
445 ));
446 self
447 }
448
449 pub fn border_right_width_px(&mut self, v: f32) -> &mut Self {
450 self.pending.push(PropertyDeclaration::BorderRightWidth(
451 style::values::specified::BorderSideWidth::from_px(v),
452 ));
453 self
454 }
455
456 pub fn border_right_style(
457 &mut self,
458 v: style::values::specified::border::BorderStyle,
459 ) -> &mut Self {
460 self.pending.push(PropertyDeclaration::BorderRightStyle(v));
461 self
462 }
463
464 pub fn border_right_color(&mut self, v: impl Into<AbsoluteColor>) -> &mut Self {
465 self.pending.push(PropertyDeclaration::BorderRightColor(
466 Color::from_absolute_color(v.into()),
467 ));
468 self
469 }
470
471 pub fn overflow_hidden(&mut self) -> &mut Self {
474 use style::values::specified::box_::Overflow;
475 self.pending
476 .push(PropertyDeclaration::OverflowX(Overflow::Hidden));
477 self.pending
478 .push(PropertyDeclaration::OverflowY(Overflow::Hidden));
479 self
480 }
481
482 #[inline]
485 fn extract_px(&self, lp: &NonNegativeLengthPercentage) -> f32 {
486 use style::values::specified::length::NoCalcLength;
487 match &lp.0 {
488 style::values::specified::LengthPercentage::Length(NoCalcLength::Absolute(
489 style::values::specified::length::AbsoluteLength::Px(v),
490 )) => *v,
491 _ => 0.0,
492 }
493 }
494
495 pub fn w(&mut self, v: impl Into<Size>) -> &mut Self {
502 self.width(v)
503 }
504 pub fn h(&mut self, v: impl Into<Size>) -> &mut Self {
506 self.height(v)
507 }
508 pub fn size(&mut self, v: impl Into<Size> + Clone) -> &mut Self {
510 self.width(v.clone());
511 self.height(v)
512 }
513 pub fn bg(&mut self, v: impl Into<AbsoluteColor>) -> &mut Self {
515 self.background_color(v)
516 }
517 pub fn flex(&mut self) -> &mut Self {
519 self.display(Display::Flex)
520 }
521 pub fn grid(&mut self) -> &mut Self {
523 self.display(Display::Grid)
524 }
525 pub fn block(&mut self) -> &mut Self {
527 self.display(Display::Block)
528 }
529 pub fn pad(&mut self, v: impl Into<NonNegativeLengthPercentage>) -> &mut Self {
531 self.padding(v)
532 }
533 pub fn mar(&mut self, v: impl Into<Margin>) -> &mut Self {
535 self.margin(v)
536 }
537
538 pub fn raw(&mut self, decl: PropertyDeclaration) -> &mut Self {
541 self.pending.push(decl);
542 self
543 }
544
545 pub fn apply(&mut self) {
550 self.flush();
551 }
552
553 fn flush(&mut self) {
554 if self.pending.is_empty() {
555 return;
556 }
557 let pending = std::mem::take(&mut self.pending);
558 let index = self.id.index();
559 self.cell.write(|doc| {
560 doc.write_element_data(self.id, |ed| {
561 for decl in pending {
562 ed.set_inline_property(decl);
563 }
564 });
565 doc.mark_for_restyle(index);
567 });
568 }
569}
570
571impl Drop for StyleAccess {
573 fn drop(&mut self) {
574 self.flush();
575 }
576}