mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:07:34 +00:00
ClockSettings: Display a map to show the current time zone's location
This commit is contained in:
parent
35cacb850a
commit
4d2ea773db
5 changed files with 97 additions and 1 deletions
BIN
Base/res/graphics/map.png
Normal file
BIN
Base/res/graphics/map.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -7,14 +7,30 @@
|
||||||
#include "ClockSettingsWidget.h"
|
#include "ClockSettingsWidget.h"
|
||||||
#include <Applications/ClockSettings/ClockSettingsWidgetGML.h>
|
#include <Applications/ClockSettings/ClockSettingsWidgetGML.h>
|
||||||
#include <LibGUI/ComboBox.h>
|
#include <LibGUI/ComboBox.h>
|
||||||
|
#include <LibGUI/Event.h>
|
||||||
|
#include <LibGUI/ImageWidget.h>
|
||||||
#include <LibGUI/ItemListModel.h>
|
#include <LibGUI/ItemListModel.h>
|
||||||
#include <LibGUI/Label.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 <LibTimeZone/TimeZone.h>
|
||||||
|
#include <math.h>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using StringViewListModel = GUI::ItemListModel<StringView, Span<StringView const>>;
|
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;
|
||||||
|
|
||||||
ClockSettingsWidget::ClockSettingsWidget()
|
ClockSettingsWidget::ClockSettingsWidget()
|
||||||
{
|
{
|
||||||
load_from_gml(clock_settings_widget_gml);
|
load_from_gml(clock_settings_widget_gml);
|
||||||
|
@ -26,19 +42,84 @@ ClockSettingsWidget::ClockSettingsWidget()
|
||||||
m_time_zone_combo_box->set_only_allow_values_from_model(true);
|
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_model(*StringViewListModel::create(time_zones));
|
||||||
m_time_zone_combo_box->set_text(m_time_zone);
|
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();
|
||||||
|
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClockSettingsWidget::reset_default_values()
|
void ClockSettingsWidget::reset_default_values()
|
||||||
{
|
{
|
||||||
m_time_zone = "UTC"sv;
|
m_time_zone = "UTC"sv;
|
||||||
m_time_zone_combo_box->set_text(m_time_zone);
|
m_time_zone_combo_box->set_text(m_time_zone);
|
||||||
|
m_time_zone_location.clear();
|
||||||
|
|
||||||
set_time_zone();
|
set_time_zone();
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClockSettingsWidget::apply_settings()
|
void ClockSettingsWidget::apply_settings()
|
||||||
{
|
{
|
||||||
m_time_zone = m_time_zone_combo_box->text();
|
m_time_zone = m_time_zone_combo_box->text();
|
||||||
|
|
||||||
|
set_time_zone_location();
|
||||||
set_time_zone();
|
set_time_zone();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClockSettingsWidget::set_time_zone_location()
|
||||||
|
{
|
||||||
|
m_time_zone_location = compute_time_zone_location();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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::set_time_zone() const
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
@GUI::GroupBox {
|
@GUI::GroupBox {
|
||||||
title: "Time Zone Settings"
|
title: "Time Zone Settings"
|
||||||
fixed_height: 120
|
|
||||||
|
|
||||||
layout: @GUI::VerticalBoxLayout {
|
layout: @GUI::VerticalBoxLayout {
|
||||||
margins: [16, 8, 8]
|
margins: [16, 8, 8]
|
||||||
|
@ -36,5 +35,10 @@
|
||||||
name: "time_zone_input"
|
name: "time_zone_input"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GUI::ImageWidget {
|
||||||
|
name: "time_zone_map"
|
||||||
|
auto_resize: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Optional.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibGUI/SettingsWindow.h>
|
#include <LibGUI/SettingsWindow.h>
|
||||||
|
@ -18,10 +19,19 @@ class ClockSettingsWidget final : public GUI::SettingsWindow::Tab {
|
||||||
private:
|
private:
|
||||||
ClockSettingsWidget();
|
ClockSettingsWidget();
|
||||||
|
|
||||||
|
virtual void second_paint_event(GUI::PaintEvent&) override;
|
||||||
|
|
||||||
virtual void apply_settings() override;
|
virtual void apply_settings() override;
|
||||||
virtual void reset_default_values() 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;
|
void set_time_zone() const;
|
||||||
|
|
||||||
String m_time_zone;
|
String m_time_zone;
|
||||||
RefPtr<GUI::ComboBox> m_time_zone_combo_box;
|
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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto window = TRY(GUI::SettingsWindow::create("Clock Settings", GUI::SettingsWindow::ShowDefaultsButton::Yes));
|
auto window = TRY(GUI::SettingsWindow::create("Clock Settings", GUI::SettingsWindow::ShowDefaultsButton::Yes));
|
||||||
(void)TRY(window->add_tab<ClockSettingsWidget>("Clock"));
|
(void)TRY(window->add_tab<ClockSettingsWidget>("Clock"));
|
||||||
window->set_icon(app_icon.bitmap_for_size(16));
|
window->set_icon(app_icon.bitmap_for_size(16));
|
||||||
|
window->resize(540, 570);
|
||||||
|
|
||||||
window->show();
|
window->show();
|
||||||
return app->exec();
|
return app->exec();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue