| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-10-26 14:30:52 +01:00
										 |  |  |  * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-01-01 18:26:19 +01:00
										 |  |  |  * Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 15:04:03 +01:00
										 |  |  | #include <LibCore/ConfigFile.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-06 12:04:00 +01:00
										 |  |  | #include <LibGfx/SystemTheme.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:00:59 -06:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 11:56:38 +01:00
										 |  |  | namespace Gfx { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | static SystemTheme dummy_theme; | 
					
						
							|  |  |  | static const SystemTheme* theme_page = &dummy_theme; | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  | static Core::AnonymousBuffer theme_buffer; | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  | Core::AnonymousBuffer& current_system_theme_buffer() | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(theme_buffer.is_valid()); | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  |     return theme_buffer; | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  | void set_system_theme(Core::AnonymousBuffer buffer) | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  |     theme_buffer = move(buffer); | 
					
						
							|  |  |  |     theme_page = theme_buffer.data<SystemTheme>(); | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 22:22:07 +02:00
										 |  |  | Core::AnonymousBuffer load_system_theme(Core::ConfigFile const& file) | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-11-06 01:20:51 +01:00
										 |  |  |     auto buffer = Core::AnonymousBuffer::create_with_size(sizeof(SystemTheme)).release_value(); | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-16 17:20:53 +01:00
										 |  |  |     auto* data = buffer.data<SystemTheme>(); | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-06 01:47:55 +02:00
										 |  |  |     auto get_color = [&](auto& name) { | 
					
						
							| 
									
										
										
										
											2021-08-25 22:22:07 +02:00
										 |  |  |         auto color_string = file.read_entry("Colors", name); | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  |         auto color = Color::from_string(color_string); | 
					
						
							|  |  |  |         if (!color.has_value()) | 
					
						
							|  |  |  |             return Color(Color::Black); | 
					
						
							|  |  |  |         return color.value(); | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 14:30:52 +01:00
										 |  |  |     auto get_flag = [&](auto& name) { | 
					
						
							| 
									
										
										
										
											2021-11-01 16:24:50 +00:00
										 |  |  |         return file.read_bool_entry("Flags", name, false); | 
					
						
							| 
									
										
										
										
											2021-10-26 14:30:52 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 18:26:19 +01:00
										 |  |  |     auto get_alignment = [&](auto& name, auto role) { | 
					
						
							|  |  |  |         auto alignment = file.read_entry("Alignments", name).to_lowercase(); | 
					
						
							|  |  |  |         if (alignment.is_empty()) { | 
					
						
							|  |  |  |             switch (role) { | 
					
						
							|  |  |  |             case (int)AlignmentRole::TitleAlignment: | 
					
						
							|  |  |  |                 return Gfx::TextAlignment::CenterLeft; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 dbgln("Alignment {} has no fallback value!", name); | 
					
						
							|  |  |  |                 return Gfx::TextAlignment::CenterLeft; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (alignment == "left" || alignment == "centerleft") | 
					
						
							|  |  |  |             return Gfx::TextAlignment::CenterLeft; | 
					
						
							|  |  |  |         else if (alignment == "right" || alignment == "centerright") | 
					
						
							|  |  |  |             return Gfx::TextAlignment::CenterRight; | 
					
						
							|  |  |  |         else if (alignment == "center") | 
					
						
							|  |  |  |             return Gfx::TextAlignment::Center; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dbgln("Alignment {} has an invalid value!", name); | 
					
						
							|  |  |  |         return Gfx::TextAlignment::CenterLeft; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 10:27:55 +10:00
										 |  |  |     auto get_metric = [&](auto& name, auto role) { | 
					
						
							| 
									
										
										
										
											2021-08-25 22:22:07 +02:00
										 |  |  |         int metric = file.read_num_entry("Metrics", name, -1); | 
					
						
							| 
									
										
										
										
											2020-07-17 10:27:55 +10:00
										 |  |  |         if (metric == -1) { | 
					
						
							|  |  |  |             switch (role) { | 
					
						
							| 
									
										
										
										
											2021-12-28 22:44:12 +01:00
										 |  |  |             case (int)MetricRole::BorderThickness: | 
					
						
							|  |  |  |                 return 4; | 
					
						
							|  |  |  |             case (int)MetricRole::BorderRadius: | 
					
						
							|  |  |  |                 return 0; | 
					
						
							| 
									
										
										
										
											2020-07-17 10:27:55 +10:00
										 |  |  |             case (int)MetricRole::TitleHeight: | 
					
						
							|  |  |  |                 return 19; | 
					
						
							|  |  |  |             case (int)MetricRole::TitleButtonHeight: | 
					
						
							|  |  |  |                 return 15; | 
					
						
							|  |  |  |             case (int)MetricRole::TitleButtonWidth: | 
					
						
							|  |  |  |                 return 15; | 
					
						
							|  |  |  |             default: | 
					
						
							| 
									
										
										
										
											2021-01-11 13:32:26 +01:00
										 |  |  |                 dbgln("Metric {} has no fallback value!", name); | 
					
						
							| 
									
										
										
										
											2020-07-17 10:27:55 +10:00
										 |  |  |                 return 16; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return metric; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  |     auto get_path = [&](auto& name, auto role, bool allow_empty) { | 
					
						
							| 
									
										
										
										
											2021-08-25 22:22:07 +02:00
										 |  |  |         auto path = file.read_entry("Paths", name); | 
					
						
							| 
									
										
										
										
											2020-07-29 16:09:04 -04:00
										 |  |  |         if (path.is_empty()) { | 
					
						
							|  |  |  |             switch (role) { | 
					
						
							|  |  |  |             case (int)PathRole::TitleButtonIcons: | 
					
						
							|  |  |  |                 return "/res/icons/16x16/"; | 
					
						
							|  |  |  |             default: | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  |                 return allow_empty ? "" : "/res/"; | 
					
						
							| 
									
										
										
										
											2020-07-29 16:09:04 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return &path[0]; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 19:51:17 +02:00
										 |  |  | #undef __ENUMERATE_COLOR_ROLE
 | 
					
						
							|  |  |  | #define __ENUMERATE_COLOR_ROLE(role) \
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:00:59 -06:00
										 |  |  |     data->color[(int)ColorRole::role] = get_color(#role).value(); | 
					
						
							| 
									
										
										
										
											2020-08-21 19:51:17 +02:00
										 |  |  |     ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE) | 
					
						
							|  |  |  | #undef __ENUMERATE_COLOR_ROLE
 | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-01 18:26:19 +01:00
										 |  |  | #undef __ENUMERATE_ALIGNMENT_ROLE
 | 
					
						
							|  |  |  | #define __ENUMERATE_ALIGNMENT_ROLE(role) \
 | 
					
						
							|  |  |  |     data->alignment[(int)AlignmentRole::role] = get_alignment(#role, (int)AlignmentRole::role); | 
					
						
							|  |  |  |     ENUMERATE_ALIGNMENT_ROLES(__ENUMERATE_ALIGNMENT_ROLE) | 
					
						
							|  |  |  | #undef __ENUMERATE_ALIGNMENT_ROLE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 14:30:52 +01:00
										 |  |  | #undef __ENUMERATE_FLAG_ROLE
 | 
					
						
							|  |  |  | #define __ENUMERATE_FLAG_ROLE(role) \
 | 
					
						
							|  |  |  |     data->flag[(int)FlagRole::role] = get_flag(#role); | 
					
						
							|  |  |  |     ENUMERATE_FLAG_ROLES(__ENUMERATE_FLAG_ROLE) | 
					
						
							|  |  |  | #undef __ENUMERATE_FLAG_ROLE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 21:05:33 +02:00
										 |  |  | #undef __ENUMERATE_METRIC_ROLE
 | 
					
						
							|  |  |  | #define __ENUMERATE_METRIC_ROLE(role) \
 | 
					
						
							|  |  |  |     data->metric[(int)MetricRole::role] = get_metric(#role, (int)MetricRole::role); | 
					
						
							|  |  |  |     ENUMERATE_METRIC_ROLES(__ENUMERATE_METRIC_ROLE) | 
					
						
							|  |  |  | #undef __ENUMERATE_METRIC_ROLE
 | 
					
						
							| 
									
										
										
										
											2020-07-17 10:27:55 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  | #define DO_PATH(x, allow_empty)                                                                                  \
 | 
					
						
							| 
									
										
										
										
											2020-09-30 20:00:59 -06:00
										 |  |  |     do {                                                                                                         \ | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  |         auto path = get_path(#x, (int)PathRole::x, allow_empty);                                                 \ | 
					
						
							| 
									
										
										
										
											2020-09-30 20:00:59 -06:00
										 |  |  |         memcpy(data->path[(int)PathRole::x], path, min(strlen(path) + 1, sizeof(data->path[(int)PathRole::x]))); \ | 
					
						
							|  |  |  |         data->path[(int)PathRole::x][sizeof(data->path[(int)PathRole::x]) - 1] = '\0';                           \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							| 
									
										
										
										
											2020-07-29 16:09:04 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  |     DO_PATH(TitleButtonIcons, false); | 
					
						
							| 
									
										
										
										
											2021-02-11 15:12:19 -07:00
										 |  |  |     DO_PATH(ActiveWindowShadow, true); | 
					
						
							|  |  |  |     DO_PATH(InactiveWindowShadow, true); | 
					
						
							| 
									
										
										
										
											2021-04-13 16:18:20 +02:00
										 |  |  |     DO_PATH(TaskbarShadow, true); | 
					
						
							| 
									
										
										
										
											2021-02-09 22:12:32 -07:00
										 |  |  |     DO_PATH(MenuShadow, true); | 
					
						
							|  |  |  |     DO_PATH(TooltipShadow, true); | 
					
						
							| 
									
										
										
										
											2020-07-29 16:09:04 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-23 20:24:26 +01:00
										 |  |  |     return buffer; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-06 11:56:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 22:22:07 +02:00
										 |  |  | Core::AnonymousBuffer load_system_theme(String const& path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return load_system_theme(Core::ConfigFile::open(path)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 11:56:38 +01:00
										 |  |  | } |