| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-10-04 13:19:50 +02:00
										 |  |  |  * Copyright (c) 2018-2022, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2023-03-23 22:54:43 +00:00
										 |  |  |  * Copyright (c) 2023, MacDue <macdue@dueutil.tech> | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-10 22:46:35 +01:00
										 |  |  | #include <LibWeb/DOM/Document.h>
 | 
					
						
							|  |  |  | #include <LibWeb/HTML/BrowsingContext.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-14 23:05:55 +00:00
										 |  |  | #include <LibWeb/HTML/HTMLInputElement.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-10 22:46:35 +01:00
										 |  |  | #include <LibWeb/Layout/Label.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | #include <LibWeb/Layout/RadioButton.h>
 | 
					
						
							| 
									
										
										
										
											2023-03-23 22:54:43 +00:00
										 |  |  | #include <LibWeb/Painting/InputColors.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | #include <LibWeb/Painting/RadioButtonPaintable.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Web::Painting { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-06 10:16:04 -07:00
										 |  |  | JS_DEFINE_ALLOCATOR(RadioButtonPaintable); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 12:51:49 +01:00
										 |  |  | JS::NonnullGCPtr<RadioButtonPaintable> RadioButtonPaintable::create(Layout::RadioButton const& layout_box) | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-11-14 06:13:46 +13:00
										 |  |  |     return layout_box.heap().allocate<RadioButtonPaintable>(layout_box); | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | RadioButtonPaintable::RadioButtonPaintable(Layout::RadioButton const& layout_box) | 
					
						
							| 
									
										
										
										
											2022-03-10 22:46:35 +01:00
										 |  |  |     : LabelablePaintable(layout_box) | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!is_visible()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-10 15:50:57 +01:00
										 |  |  |     PaintableBox::paint(context, phase); | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-23 22:54:43 +00:00
										 |  |  |     if (phase != PaintPhase::Foreground) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto draw_circle = [&](auto const& rect, Color color) { | 
					
						
							|  |  |  |         // Note: Doing this is a bit more forgiving than draw_circle() which will round to the nearset even radius.
 | 
					
						
							|  |  |  |         // This will fudge it (which works better here).
 | 
					
						
							| 
									
										
										
										
											2024-06-23 18:40:10 +02:00
										 |  |  |         context.display_list_recorder().fill_rect_with_rounded_corners(rect, color, rect.width() / 2); | 
					
						
							| 
									
										
										
										
											2023-03-23 22:54:43 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto shrink_all = [&](auto const& rect, int amount) { | 
					
						
							|  |  |  |         return rect.shrunken(amount, amount, amount, amount); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto const& radio_button = static_cast<HTML::HTMLInputElement const&>(layout_box().dom_node()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& palette = context.palette(); | 
					
						
							|  |  |  |     bool enabled = layout_box().dom_node().enabled(); | 
					
						
							|  |  |  |     auto input_colors = compute_input_colors(palette, computed_values().accent_color()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto background_color = input_colors.background_color(enabled); | 
					
						
							|  |  |  |     auto accent = input_colors.accent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto radio_color = [&] { | 
					
						
							|  |  |  |         if (radio_button.checked()) { | 
					
						
							|  |  |  |             // Handle the awkward case where a light color has been used for the accent color.
 | 
					
						
							|  |  |  |             if (accent.contrast_ratio(background_color) < 2 && accent.contrast_ratio(input_colors.dark_gray) > 2) | 
					
						
							|  |  |  |                 background_color = input_colors.dark_gray; | 
					
						
							|  |  |  |             return accent; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return input_colors.gray; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto fill_color = [&] { | 
					
						
							|  |  |  |         if (!enabled) | 
					
						
							|  |  |  |             return input_colors.mid_gray; | 
					
						
							|  |  |  |         auto color = radio_color(); | 
					
						
							|  |  |  |         if (being_pressed()) | 
					
						
							|  |  |  |             color = InputColors::get_shade(color, 0.3f, palette.is_dark()); | 
					
						
							|  |  |  |         return color; | 
					
						
							|  |  |  |     }(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This is based on a 1px outer border and 2px inner border when drawn at 13x13.
 | 
					
						
							|  |  |  |     auto radio_button_rect = context.enclosing_device_rect(absolute_rect()).to_type<int>(); | 
					
						
							|  |  |  |     auto outer_border_width = max(1, static_cast<int>(ceilf(radio_button_rect.width() / 13.0f))); | 
					
						
							|  |  |  |     auto inner_border_width = max(2, static_cast<int>(ceilf(radio_button_rect.width() / 4.0f))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     draw_circle(radio_button_rect, fill_color); | 
					
						
							|  |  |  |     draw_circle(shrink_all(radio_button_rect, outer_border_width), background_color); | 
					
						
							|  |  |  |     if (radio_button.checked()) | 
					
						
							|  |  |  |         draw_circle(shrink_all(radio_button_rect, inner_border_width), fill_color); | 
					
						
							| 
									
										
										
										
											2022-03-10 14:02:25 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |