diff options
author | cflip <cflip@cflip.net> | 2022-04-03 17:13:52 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-04 13:15:13 +0200 |
commit | 5bb0b6ba7ab1bcb6e11f081a3103bcd44d597090 (patch) | |
tree | 43676efd1019225f1369912b595a12770ec9be1a /Userland | |
parent | 36b6356ce51375a99b08cabd7bce8e5455a8fb0d (diff) | |
download | serenity-5bb0b6ba7ab1bcb6e11f081a3103bcd44d597090.zip |
ClockSettings+Taskbar: Add settings for taskbar clock format
Diffstat (limited to 'Userland')
12 files changed, 331 insertions, 179 deletions
diff --git a/Userland/Applications/ClockSettings/CMakeLists.txt b/Userland/Applications/ClockSettings/CMakeLists.txt index 94186a3efb..39cee55209 100644 --- a/Userland/Applications/ClockSettings/CMakeLists.txt +++ b/Userland/Applications/ClockSettings/CMakeLists.txt @@ -5,12 +5,16 @@ serenity_component( ) compile_gml(ClockSettingsWidget.gml ClockSettingsWidgetGML.h clock_settings_widget_gml) +compile_gml(TimeZoneSettingsWidget.gml TimeZoneSettingsWidgetGML.h time_zone_settings_widget_gml) set(SOURCES main.cpp ClockSettingsWidget.cpp ClockSettingsWidget.h ClockSettingsWidgetGML.h + TimeZoneSettingsWidget.cpp + TimeZoneSettingsWidget.h + TimeZoneSettingsWidgetGML.h ) serenity_app(ClockSettings ICON app-analog-clock) # FIXME: Create a ClockSettings icon. diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp b/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp index 98c86b18d8..9c8dc78eb5 100644 --- a/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp +++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.cpp @@ -1,165 +1,49 @@ /* - * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> + * Copyright (c) 2022, cflip <cflip@cflip.net> * * SPDX-License-Identifier: BSD-2-Clause */ #include "ClockSettingsWidget.h" -#include <AK/Time.h> #include <Applications/ClockSettings/ClockSettingsWidgetGML.h> -#include <LibGUI/ComboBox.h> -#include <LibGUI/Event.h> -#include <LibGUI/ImageWidget.h> -#include <LibGUI/ItemListModel.h> -#include <LibGUI/Label.h> -#include <LibGUI/Layout.h> -#include <LibGUI/Margins.h> -#include <LibGUI/Painter.h> -#include <LibGfx/Palette.h> -#include <LibTimeZone/TimeZone.h> -#include <LibUnicode/DateTimeFormat.h> -#include <LibUnicode/Locale.h> -#include <math.h> -#include <spawn.h> -#include <unistd.h> - -using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>; - -static constexpr auto PI_OVER_180 = M_PIf32 / 180.0f; -static constexpr auto PI_OVER_4 = M_PIf32 / 4.0f; -static constexpr auto TAU = M_PIf32 * 2.0f; - -// The map as stored on disk is a valid Mercadian projected map. But it has quite a bit of dead space that -// we can remove. This makes the map non-Mercadian, so we need to adjust our math based on what we removed. -static constexpr auto TIME_ZONE_MAP_NORTHERN_TRIM = 78; -static constexpr auto TIME_ZONE_MAP_SOUTHERN_TRIM = 50; - -static constexpr auto TIME_ZONE_TEXT_WIDTH = 210; -static constexpr auto TIME_ZONE_TEXT_HEIGHT = 40; -static constexpr auto TIME_ZONE_TEXT_PADDING = 5; -static constexpr auto TIME_ZONE_TEXT_COLOR = Gfx::Color::from_rgb(0xeaf688); +#include <LibConfig/Client.h> +#include <LibGUI/RadioButton.h> +#include <LibGUI/TextBox.h> ClockSettingsWidget::ClockSettingsWidget() { load_from_gml(clock_settings_widget_gml); - static auto time_zones = TimeZone::all_time_zones(); - m_time_zone = TimeZone::system_time_zone(); - - m_time_zone_combo_box = *find_descendant_of_type_named<GUI::ComboBox>("time_zone_input"); - m_time_zone_combo_box->set_only_allow_values_from_model(true); - m_time_zone_combo_box->set_model(*StringViewListModel::create(time_zones)); - m_time_zone_combo_box->set_text(m_time_zone); - - auto time_zone_map_bitmap = Gfx::Bitmap::try_load_from_file("/res/graphics/map.png"sv).release_value_but_fixme_should_propagate_errors(); - auto time_zone_rect = time_zone_map_bitmap->rect().shrunken(TIME_ZONE_MAP_NORTHERN_TRIM, 0, TIME_ZONE_MAP_SOUTHERN_TRIM, 0); - time_zone_map_bitmap = time_zone_map_bitmap->cropped(time_zone_rect).release_value_but_fixme_should_propagate_errors(); - - m_time_zone_map = *find_descendant_of_type_named<GUI::ImageWidget>("time_zone_map"); - m_time_zone_map->set_bitmap(time_zone_map_bitmap); - - auto time_zone_marker = Gfx::Bitmap::try_load_from_file("/res/icons/32x32/ladyball.png").release_value_but_fixme_should_propagate_errors(); - m_time_zone_marker = time_zone_marker->scaled(0.75f, 0.75f).release_value_but_fixme_should_propagate_errors(); - - set_time_zone_location(); -} - -void ClockSettingsWidget::second_paint_event(GUI::PaintEvent& event) -{ - GUI::Widget::second_paint_event(event); - - if (!m_time_zone_location.has_value()) - return; - - GUI::Painter painter(*this); - painter.add_clip_rect(event.rect()); - painter.add_clip_rect(m_time_zone_map->relative_rect()); - - auto x = m_time_zone_map->x() + m_time_zone_map->parent_widget()->layout()->margins().left(); - auto y = m_time_zone_map->y() + m_time_zone_map->parent_widget()->layout()->margins().top(); + m_24_hour_radio = *find_descendant_of_type_named<GUI::RadioButton>("24hour_radio"); + auto& twelve_hour_radio = *find_descendant_of_type_named<GUI::RadioButton>("12hour_radio"); + auto& custom_radio = *find_descendant_of_type_named<GUI::RadioButton>("custom_radio"); + custom_radio.set_checked(true); - auto point = m_time_zone_location->to_type<int>().translated(x, y); - point.translate_by(-m_time_zone_marker->width() / 2, -m_time_zone_marker->height() / 2); - painter.blit(point, *m_time_zone_marker, rect()); + m_custom_format_input = *find_descendant_of_type_named<GUI::TextBox>("custom_format_input"); + m_custom_format_input->set_text(Config::read_string("Taskbar", "Clock", "TimeFormat")); - point = m_time_zone_location->to_type<int>().translated(x, y); - point.translate_by(0, -TIME_ZONE_TEXT_HEIGHT / 2); + m_24_hour_radio->on_checked = [&](bool) { + m_custom_format_input->set_enabled(false); + m_custom_format_input->set_text("%T"); + }; - if (point.x() <= (m_time_zone_map->width() / 2)) - point.translate_by(m_time_zone_marker->width() / 2 + TIME_ZONE_TEXT_PADDING, 0); - else - point.translate_by(-m_time_zone_marker->width() / 2 - TIME_ZONE_TEXT_PADDING - TIME_ZONE_TEXT_WIDTH, 0); + twelve_hour_radio.on_checked = [&](bool) { + m_custom_format_input->set_enabled(false); + m_custom_format_input->set_text("%I:%M %p"); + }; - auto text_area = Gfx::IntRect { point.x(), point.y(), TIME_ZONE_TEXT_WIDTH, TIME_ZONE_TEXT_HEIGHT }; - painter.draw_rect(text_area, palette().active_window_border1()); - - text_area.shrink(2, 2); - painter.fill_rect(text_area, TIME_ZONE_TEXT_COLOR); - painter.draw_text(text_area, m_time_zone_text, Gfx::TextAlignment::Center); -} - -void ClockSettingsWidget::reset_default_values() -{ - m_time_zone = "UTC"sv; - m_time_zone_combo_box->set_text(m_time_zone); - m_time_zone_location.clear(); - - set_time_zone(); - update(); + custom_radio.on_checked = [&](bool) { + m_custom_format_input->set_enabled(true); + }; } void ClockSettingsWidget::apply_settings() { - m_time_zone = m_time_zone_combo_box->text(); - - set_time_zone_location(); - set_time_zone(); - update(); -} - -void ClockSettingsWidget::set_time_zone_location() -{ - m_time_zone_location = compute_time_zone_location(); - - auto locale = Unicode::default_locale(); - auto now = AK::Time::now_realtime(); - - auto name = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::Long, now); - auto offset = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::LongOffset, now); - - m_time_zone_text = String::formatted("{}\n({})", name, offset); + Config::write_string("Taskbar", "Clock", "TimeFormat", m_custom_format_input->text()); } -// https://en.wikipedia.org/wiki/Mercator_projection#Derivation -Optional<Gfx::FloatPoint> ClockSettingsWidget::compute_time_zone_location() const -{ - auto location = TimeZone::get_time_zone_location(m_time_zone); - if (!location.has_value()) - return {}; - - auto latitude = location->latitude.decimal_coordinate(); - auto longitude = location->longitude.decimal_coordinate(); - - auto rect = m_time_zone_map->bitmap()->rect().to_type<float>(); - - latitude = logf(tanf(PI_OVER_4 + (latitude * PI_OVER_180 / 2.0f))); - - auto mercadian_x = (longitude + 180.0f) * (rect.width() / 360.0f); - auto mercadian_y = (rect.height() / 2.0f) - (rect.width() * latitude / TAU); - - mercadian_y -= TIME_ZONE_MAP_NORTHERN_TRIM / 2; - mercadian_y += TIME_ZONE_MAP_SOUTHERN_TRIM / 2; - - return Gfx::FloatPoint { mercadian_x, mercadian_y }; -} - -void ClockSettingsWidget::set_time_zone() const +void ClockSettingsWidget::reset_default_values() { - pid_t child_pid = 0; - char const* argv[] = { "/bin/timezone", m_time_zone.characters(), nullptr }; - - if ((errno = posix_spawn(&child_pid, "/bin/timezone", nullptr, nullptr, const_cast<char**>(argv), environ))) { - perror("posix_spawn"); - exit(1); - } + m_24_hour_radio->set_checked(true); + Config::write_string("Taskbar", "Clock", "TimeFormat", "%T"); } diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.gml b/Userland/Applications/ClockSettings/ClockSettingsWidget.gml index f0b10cd4a8..f6f66dc92d 100644 --- a/Userland/Applications/ClockSettings/ClockSettingsWidget.gml +++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.gml @@ -6,37 +6,42 @@ } @GUI::GroupBox { - title: "Time Zone Settings" + title: "Time Format" + shrink_to_fit: false + fixed_height: 160 layout: @GUI::VerticalBoxLayout { margins: [16, 8, 8] - spacing: 16 } @GUI::Label { - text: "Change the system's time zone used for the clock and other applications." + text: "Set the date/time format used by the taskbar clock." text_alignment: "TopLeft" } @GUI::Widget { - layout: @GUI::HorizontalBoxLayout { + shrink_to_fit: true + layout: @GUI::VerticalBoxLayout { spacing: 4 } - @GUI::Label { - text: "Time Zone:" - fixed_width: 80 - name: "time_zone_label" - text_alignment: "CenterLeft" + @GUI::RadioButton { + name: "24hour_radio" + text: "24-hour (12:34:56)" } - @GUI::ComboBox { - name: "time_zone_input" + @GUI::RadioButton { + name: "12hour_radio" + text: "12-hour (12:34 a.m)" + } + + @GUI::RadioButton { + name: "custom_radio" + text: "Custom:" } - } - @GUI::ImageWidget { - name: "time_zone_map" - auto_resize: true + @GUI::TextBox { + name: "custom_format_input" + } } } } diff --git a/Userland/Applications/ClockSettings/ClockSettingsWidget.h b/Userland/Applications/ClockSettings/ClockSettingsWidget.h index b2394a783a..35f5becc62 100644 --- a/Userland/Applications/ClockSettings/ClockSettingsWidget.h +++ b/Userland/Applications/ClockSettings/ClockSettingsWidget.h @@ -1,17 +1,13 @@ /* - * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> + * Copyright (c) 2022, cflip <cflip@cflip.net> * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include <AK/Optional.h> #include <AK/RefPtr.h> -#include <AK/String.h> #include <LibGUI/SettingsWindow.h> -#include <LibGUI/TextEditor.h> -#include <LibGUI/Window.h> class ClockSettingsWidget final : public GUI::SettingsWindow::Tab { C_OBJECT(ClockSettingsWidget) @@ -19,20 +15,11 @@ class ClockSettingsWidget final : public GUI::SettingsWindow::Tab { private: ClockSettingsWidget(); - virtual void second_paint_event(GUI::PaintEvent&) override; - virtual void apply_settings() override; virtual void reset_default_values() override; - void set_time_zone_location(); - Optional<Gfx::FloatPoint> compute_time_zone_location() const; - void set_time_zone() const; - - String m_time_zone; - RefPtr<GUI::ComboBox> m_time_zone_combo_box; - RefPtr<GUI::ImageWidget> m_time_zone_map; - RefPtr<Gfx::Bitmap> m_time_zone_marker; + RefPtr<GUI::RadioButton> m_24_hour_radio; + RefPtr<GUI::TextBox> m_custom_format_input; - Optional<Gfx::FloatPoint> m_time_zone_location; - String m_time_zone_text; + String m_date_format; }; diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp new file mode 100644 index 0000000000..6dcfc93fa4 --- /dev/null +++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "TimeZoneSettingsWidget.h" +#include <AK/Time.h> +#include <Applications/ClockSettings/TimeZoneSettingsWidgetGML.h> +#include <LibGUI/ComboBox.h> +#include <LibGUI/Event.h> +#include <LibGUI/ImageWidget.h> +#include <LibGUI/ItemListModel.h> +#include <LibGUI/Label.h> +#include <LibGUI/Layout.h> +#include <LibGUI/Margins.h> +#include <LibGUI/Painter.h> +#include <LibGfx/Palette.h> +#include <LibTimeZone/TimeZone.h> +#include <LibUnicode/DateTimeFormat.h> +#include <LibUnicode/Locale.h> +#include <math.h> +#include <spawn.h> +#include <unistd.h> + +using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>; + +static constexpr auto PI_OVER_180 = M_PIf32 / 180.0f; +static constexpr auto PI_OVER_4 = M_PIf32 / 4.0f; +static constexpr auto TAU = M_PIf32 * 2.0f; + +// The map as stored on disk is a valid Mercadian projected map. But it has quite a bit of dead space that +// we can remove. This makes the map non-Mercadian, so we need to adjust our math based on what we removed. +static constexpr auto TIME_ZONE_MAP_NORTHERN_TRIM = 78; +static constexpr auto TIME_ZONE_MAP_SOUTHERN_TRIM = 50; + +static constexpr auto TIME_ZONE_TEXT_WIDTH = 210; +static constexpr auto TIME_ZONE_TEXT_HEIGHT = 40; +static constexpr auto TIME_ZONE_TEXT_PADDING = 5; +static constexpr auto TIME_ZONE_TEXT_COLOR = Gfx::Color::from_rgb(0xeaf688); + +TimeZoneSettingsWidget::TimeZoneSettingsWidget() +{ + load_from_gml(time_zone_settings_widget_gml); + + static auto time_zones = TimeZone::all_time_zones(); + m_time_zone = TimeZone::system_time_zone(); + + m_time_zone_combo_box = *find_descendant_of_type_named<GUI::ComboBox>("time_zone_input"); + m_time_zone_combo_box->set_only_allow_values_from_model(true); + m_time_zone_combo_box->set_model(*StringViewListModel::create(time_zones)); + m_time_zone_combo_box->set_text(m_time_zone); + + auto time_zone_map_bitmap = Gfx::Bitmap::try_load_from_file("/res/graphics/map.png"sv).release_value_but_fixme_should_propagate_errors(); + auto time_zone_rect = time_zone_map_bitmap->rect().shrunken(TIME_ZONE_MAP_NORTHERN_TRIM, 0, TIME_ZONE_MAP_SOUTHERN_TRIM, 0); + time_zone_map_bitmap = time_zone_map_bitmap->cropped(time_zone_rect).release_value_but_fixme_should_propagate_errors(); + + m_time_zone_map = *find_descendant_of_type_named<GUI::ImageWidget>("time_zone_map"); + m_time_zone_map->set_bitmap(time_zone_map_bitmap); + + auto time_zone_marker = Gfx::Bitmap::try_load_from_file("/res/icons/32x32/ladyball.png").release_value_but_fixme_should_propagate_errors(); + m_time_zone_marker = time_zone_marker->scaled(0.75f, 0.75f).release_value_but_fixme_should_propagate_errors(); + + set_time_zone_location(); +} + +void TimeZoneSettingsWidget::second_paint_event(GUI::PaintEvent& event) +{ + GUI::Widget::second_paint_event(event); + + if (!m_time_zone_location.has_value()) + return; + + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + painter.add_clip_rect(m_time_zone_map->relative_rect()); + + auto x = m_time_zone_map->x() + m_time_zone_map->parent_widget()->layout()->margins().left(); + auto y = m_time_zone_map->y() + m_time_zone_map->parent_widget()->layout()->margins().top(); + + auto point = m_time_zone_location->to_type<int>().translated(x, y); + point.translate_by(-m_time_zone_marker->width() / 2, -m_time_zone_marker->height() / 2); + painter.blit(point, *m_time_zone_marker, rect()); + + point = m_time_zone_location->to_type<int>().translated(x, y); + point.translate_by(0, -TIME_ZONE_TEXT_HEIGHT / 2); + + if (point.x() <= (m_time_zone_map->width() / 2)) + point.translate_by(m_time_zone_marker->width() / 2 + TIME_ZONE_TEXT_PADDING, 0); + else + point.translate_by(-m_time_zone_marker->width() / 2 - TIME_ZONE_TEXT_PADDING - TIME_ZONE_TEXT_WIDTH, 0); + + auto text_area = Gfx::IntRect { point.x(), point.y(), TIME_ZONE_TEXT_WIDTH, TIME_ZONE_TEXT_HEIGHT }; + painter.draw_rect(text_area, palette().active_window_border1()); + + text_area.shrink(2, 2); + painter.fill_rect(text_area, TIME_ZONE_TEXT_COLOR); + painter.draw_text(text_area, m_time_zone_text, Gfx::TextAlignment::Center); +} + +void TimeZoneSettingsWidget::reset_default_values() +{ + m_time_zone = "UTC"sv; + m_time_zone_combo_box->set_text(m_time_zone); + m_time_zone_location.clear(); + + set_time_zone(); + update(); +} + +void TimeZoneSettingsWidget::apply_settings() +{ + m_time_zone = m_time_zone_combo_box->text(); + + set_time_zone_location(); + set_time_zone(); + update(); +} + +void TimeZoneSettingsWidget::set_time_zone_location() +{ + m_time_zone_location = compute_time_zone_location(); + + auto locale = Unicode::default_locale(); + auto now = AK::Time::now_realtime(); + + auto name = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::Long, now); + auto offset = Unicode::format_time_zone(locale, m_time_zone, Unicode::CalendarPatternStyle::LongOffset, now); + + m_time_zone_text = String::formatted("{}\n({})", name, offset); +} + +// https://en.wikipedia.org/wiki/Mercator_projection#Derivation +Optional<Gfx::FloatPoint> TimeZoneSettingsWidget::compute_time_zone_location() const +{ + auto location = TimeZone::get_time_zone_location(m_time_zone); + if (!location.has_value()) + return {}; + + auto latitude = location->latitude.decimal_coordinate(); + auto longitude = location->longitude.decimal_coordinate(); + + auto rect = m_time_zone_map->bitmap()->rect().to_type<float>(); + + latitude = logf(tanf(PI_OVER_4 + (latitude * PI_OVER_180 / 2.0f))); + + auto mercadian_x = (longitude + 180.0f) * (rect.width() / 360.0f); + auto mercadian_y = (rect.height() / 2.0f) - (rect.width() * latitude / TAU); + + mercadian_y -= TIME_ZONE_MAP_NORTHERN_TRIM / 2; + mercadian_y += TIME_ZONE_MAP_SOUTHERN_TRIM / 2; + + return Gfx::FloatPoint { mercadian_x, mercadian_y }; +} + +void TimeZoneSettingsWidget::set_time_zone() const +{ + pid_t child_pid = 0; + char const* argv[] = { "/bin/timezone", m_time_zone.characters(), nullptr }; + + if ((errno = posix_spawn(&child_pid, "/bin/timezone", nullptr, nullptr, const_cast<char**>(argv), environ))) { + perror("posix_spawn"); + exit(1); + } +} diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml new file mode 100644 index 0000000000..f0b10cd4a8 --- /dev/null +++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.gml @@ -0,0 +1,42 @@ +@GUI::Frame { + fill_with_background_color: true + layout: @GUI::VerticalBoxLayout { + margins: [10] + spacing: 5 + } + + @GUI::GroupBox { + title: "Time Zone Settings" + layout: @GUI::VerticalBoxLayout { + margins: [16, 8, 8] + spacing: 16 + } + + @GUI::Label { + text: "Change the system's time zone used for the clock and other applications." + text_alignment: "TopLeft" + } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 4 + } + + @GUI::Label { + text: "Time Zone:" + fixed_width: 80 + name: "time_zone_label" + text_alignment: "CenterLeft" + } + + @GUI::ComboBox { + name: "time_zone_input" + } + } + + @GUI::ImageWidget { + name: "time_zone_map" + auto_resize: true + } + } +} diff --git a/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h new file mode 100644 index 0000000000..768fb0b421 --- /dev/null +++ b/Userland/Applications/ClockSettings/TimeZoneSettingsWidget.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Optional.h> +#include <AK/RefPtr.h> +#include <AK/String.h> +#include <LibGUI/SettingsWindow.h> +#include <LibGUI/TextEditor.h> +#include <LibGUI/Window.h> + +class TimeZoneSettingsWidget final : public GUI::SettingsWindow::Tab { + C_OBJECT(TimeZoneSettingsWidget) + +private: + TimeZoneSettingsWidget(); + + virtual void second_paint_event(GUI::PaintEvent&) override; + + virtual void apply_settings() override; + virtual void reset_default_values() override; + + void set_time_zone_location(); + Optional<Gfx::FloatPoint> compute_time_zone_location() const; + void set_time_zone() const; + + String m_time_zone; + RefPtr<GUI::ComboBox> m_time_zone_combo_box; + RefPtr<GUI::ImageWidget> m_time_zone_map; + RefPtr<Gfx::Bitmap> m_time_zone_marker; + + Optional<Gfx::FloatPoint> m_time_zone_location; + String m_time_zone_text; +}; diff --git a/Userland/Applications/ClockSettings/main.cpp b/Userland/Applications/ClockSettings/main.cpp index 7463e3547c..72e81ea944 100644 --- a/Userland/Applications/ClockSettings/main.cpp +++ b/Userland/Applications/ClockSettings/main.cpp @@ -5,6 +5,8 @@ */ #include "ClockSettingsWidget.h" +#include "TimeZoneSettingsWidget.h" +#include <LibConfig/Client.h> #include <LibCore/System.h> #include <LibGUI/Application.h> #include <LibGUI/Icon.h> @@ -17,6 +19,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) auto app = TRY(GUI::Application::try_create(arguments)); + Config::pledge_domain("Taskbar"); TRY(Core::System::pledge("stdio rpath recvfd sendfd proc exec")); TRY(Core::System::unveil("/res", "r")); TRY(Core::System::unveil("/bin/timezone", "x")); @@ -27,6 +30,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) auto window = TRY(GUI::SettingsWindow::create("Clock Settings", GUI::SettingsWindow::ShowDefaultsButton::Yes)); (void)TRY(window->add_tab<ClockSettingsWidget>("Clock")); + (void)TRY(window->add_tab<TimeZoneSettingsWidget>("Time Zone")); window->set_icon(app_icon.bitmap_for_size(16)); window->resize(540, 570); diff --git a/Userland/Services/Taskbar/ClockWidget.cpp b/Userland/Services/Taskbar/ClockWidget.cpp index 87a0282530..296a5f7909 100644 --- a/Userland/Services/Taskbar/ClockWidget.cpp +++ b/Userland/Services/Taskbar/ClockWidget.cpp @@ -5,6 +5,7 @@ */ #include "ClockWidget.h" +#include <LibConfig/Client.h> #include <LibCore/Process.h> #include <LibGUI/Painter.h> #include <LibGUI/SeparatorWidget.h> @@ -20,9 +21,7 @@ ClockWidget::ClockWidget() set_frame_shadow(Gfx::FrameShadow::Sunken); set_frame_thickness(1); - m_time_width = font().width("22:22:22"); - - set_fixed_size(m_time_width + 20, 21); + update_format(Config::read_string("Taskbar", "Clock", "TimeFormat", "%T")); m_timer = add<Core::Timer>(1000, [this] { static time_t last_update_time; @@ -159,10 +158,17 @@ ClockWidget::ClockWidget() }; } +void ClockWidget::update_format(String const& format) +{ + m_time_format = format; + m_time_width = font().width(Core::DateTime::create(122, 2, 22, 22, 22, 22).to_string(format)); + set_fixed_size(m_time_width + 20, 21); +} + void ClockWidget::paint_event(GUI::PaintEvent& event) { GUI::Frame::paint_event(event); - auto time_text = Core::DateTime::now().to_string("%T"); + auto time_text = Core::DateTime::now().to_string(m_time_format); GUI::Painter painter(*this); painter.add_clip_rect(frame_inner_rect()); diff --git a/Userland/Services/Taskbar/ClockWidget.h b/Userland/Services/Taskbar/ClockWidget.h index 5d28827df7..420d02a61a 100644 --- a/Userland/Services/Taskbar/ClockWidget.h +++ b/Userland/Services/Taskbar/ClockWidget.h @@ -24,6 +24,8 @@ class ClockWidget final : public GUI::Frame { public: virtual ~ClockWidget() override = default; + void update_format(String const&); + private: ClockWidget(); @@ -42,6 +44,7 @@ private: void position_calendar_window(); void jump_to_current_date(); + String m_time_format; RefPtr<GUI::Window> m_calendar_window; RefPtr<GUI::Calendar> m_calendar; RefPtr<GUI::Button> m_next_date; diff --git a/Userland/Services/Taskbar/TaskbarWindow.cpp b/Userland/Services/Taskbar/TaskbarWindow.cpp index e3cf43dcf8..bdaa045c9f 100644 --- a/Userland/Services/Taskbar/TaskbarWindow.cpp +++ b/Userland/Services/Taskbar/TaskbarWindow.cpp @@ -85,7 +85,7 @@ TaskbarWindow::TaskbarWindow(NonnullRefPtr<GUI::Menu> start_menu) m_applet_area_container->set_frame_shape(Gfx::FrameShape::Box); m_applet_area_container->set_frame_shadow(Gfx::FrameShadow::Sunken); - main_widget.add<Taskbar::ClockWidget>(); + m_clock_widget = main_widget.add<Taskbar::ClockWidget>(); m_show_desktop_button = GUI::Button::construct(); m_show_desktop_button->set_tooltip("Show Desktop"); @@ -99,6 +99,15 @@ TaskbarWindow::TaskbarWindow(NonnullRefPtr<GUI::Menu> start_menu) m_assistant_app_file = Desktop::AppFile::open(af_path); } +void TaskbarWindow::config_string_did_change(String const& domain, String const& group, String const& key, String const& value) +{ + VERIFY(domain == "Taskbar"); + if (group == "Clock" && key == "TimeFormat") { + m_clock_widget->update_format(value); + update_applet_area(); + } +} + void TaskbarWindow::show_desktop_button_clicked(unsigned) { GUI::ConnectionToWindowMangerServer::the().async_toggle_show_desktop(); diff --git a/Userland/Services/Taskbar/TaskbarWindow.h b/Userland/Services/Taskbar/TaskbarWindow.h index bfc0ceb6fa..656f4873a5 100644 --- a/Userland/Services/Taskbar/TaskbarWindow.h +++ b/Userland/Services/Taskbar/TaskbarWindow.h @@ -6,6 +6,7 @@ #pragma once +#include "ClockWidget.h" #include "WindowList.h" #include <LibConfig/Listener.h> #include <LibDesktop/AppFile.h> @@ -14,7 +15,8 @@ #include <LibGfx/ShareableBitmap.h> #include <Services/WindowServer/ScreenLayout.h> -class TaskbarWindow final : public GUI::Window { +class TaskbarWindow final : public GUI::Window + , public Config::Listener { C_OBJECT(TaskbarWindow); public: @@ -23,6 +25,8 @@ public: static int taskbar_height() { return 27; } static int taskbar_icon_size() { return 16; } + virtual void config_string_did_change(String const&, String const&, String const&, String const&) override; + private: explicit TaskbarWindow(NonnullRefPtr<GUI::Menu> start_menu); static void show_desktop_button_clicked(unsigned); @@ -53,6 +57,7 @@ private: RefPtr<GUI::Frame> m_applet_area_container; RefPtr<GUI::Button> m_start_button; RefPtr<GUI::Button> m_show_desktop_button; + RefPtr<Taskbar::ClockWidget> m_clock_widget; RefPtr<Desktop::AppFile> m_assistant_app_file; |