mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 10:27:34 +00:00
Maps: Add panels to map widget
This commit is contained in:
parent
048e8d7744
commit
599a37aa0c
2 changed files with 64 additions and 31 deletions
|
@ -8,6 +8,7 @@
|
||||||
#include "MapWidget.h"
|
#include "MapWidget.h"
|
||||||
#include <AK/URL.h>
|
#include <AK/URL.h>
|
||||||
#include <LibDesktop/Launcher.h>
|
#include <LibDesktop/Launcher.h>
|
||||||
|
#include <LibGUI/Application.h>
|
||||||
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
||||||
#include <LibProtocol/Request.h>
|
#include <LibProtocol/Request.h>
|
||||||
|
|
||||||
|
@ -54,10 +55,10 @@ MapWidget::MapWidget(Options const& options)
|
||||||
, m_scale_enabled(options.scale_enabled)
|
, m_scale_enabled(options.scale_enabled)
|
||||||
, m_scale_max_width(options.scale_max_width)
|
, m_scale_max_width(options.scale_max_width)
|
||||||
, m_attribution_enabled(options.attribution_enabled)
|
, m_attribution_enabled(options.attribution_enabled)
|
||||||
, m_attribution_text(options.attribution_text)
|
|
||||||
, m_attribution_url(options.attribution_url)
|
|
||||||
{
|
{
|
||||||
m_request_client = Protocol::RequestClient::try_create().release_value_but_fixme_should_propagate_errors();
|
m_request_client = Protocol::RequestClient::try_create().release_value_but_fixme_should_propagate_errors();
|
||||||
|
if (options.attribution_enabled)
|
||||||
|
add_panel({ options.attribution_text, Panel::Position::BottomRight, options.attribution_url, true });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWidget::set_zoom(int zoom)
|
void MapWidget::set_zoom(int zoom)
|
||||||
|
@ -79,9 +80,10 @@ void MapWidget::mousedown_event(GUI::MouseEvent& event)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (event.button() == GUI::MouseButton::Primary) {
|
if (event.button() == GUI::MouseButton::Primary) {
|
||||||
// Ignore attribution click
|
// Ignore panels click
|
||||||
if (m_attribution_enabled && static_cast<float>(event.x()) > frame_inner_rect().right() - m_attribution_width && static_cast<float>(event.y()) > frame_inner_rect().bottom() - m_attribution_height)
|
for (auto& panel : m_panels)
|
||||||
return;
|
if (panel.rect.contains(event.x(), event.y()))
|
||||||
|
return;
|
||||||
|
|
||||||
// Start map tiles dragging
|
// Start map tiles dragging
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
|
@ -107,14 +109,11 @@ void MapWidget::mousemove_event(GUI::MouseEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle attribution hover
|
// Handle panels hover
|
||||||
if (m_attribution_enabled) {
|
for (auto& panel : m_panels)
|
||||||
if (static_cast<float>(event.x()) > frame_inner_rect().right() - m_attribution_width && static_cast<float>(event.y()) > frame_inner_rect().bottom() - m_attribution_height) {
|
if (panel.url.has_value() && panel.rect.contains(event.x(), event.y()))
|
||||||
set_override_cursor(Gfx::StandardCursor::Hand);
|
return set_override_cursor(Gfx::StandardCursor::Hand);
|
||||||
} else {
|
set_override_cursor(Gfx::StandardCursor::Arrow);
|
||||||
set_override_cursor(Gfx::StandardCursor::Arrow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWidget::mouseup_event(GUI::MouseEvent& event)
|
void MapWidget::mouseup_event(GUI::MouseEvent& event)
|
||||||
|
@ -130,10 +129,12 @@ void MapWidget::mouseup_event(GUI::MouseEvent& event)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.button() == GUI::MouseButton::Primary) {
|
if (event.button() == GUI::MouseButton::Primary) {
|
||||||
// Handle attribution click
|
// Handle panels click
|
||||||
if (m_attribution_enabled && static_cast<float>(event.x()) > frame_inner_rect().right() - m_attribution_width && static_cast<float>(event.y()) > frame_inner_rect().bottom() - m_attribution_height) {
|
for (auto& panel : m_panels) {
|
||||||
Desktop::Launcher::open(m_attribution_url);
|
if (panel.url.has_value() && panel.rect.contains(event.x(), event.y())) {
|
||||||
return;
|
Desktop::Launcher::open(panel.url.value());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,13 +368,24 @@ void MapWidget::paint_scale(GUI::Painter& painter)
|
||||||
painter.fill_rect({ frame_inner_rect().x() + margin_x, frame_inner_rect().bottom() - margin_y - line_height, max(metric_width, imperial_width), 1.0f }, panel_foreground_color);
|
painter.fill_rect({ frame_inner_rect().x() + margin_x, frame_inner_rect().bottom() - margin_y - line_height, max(metric_width, imperial_width), 1.0f }, panel_foreground_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWidget::paint_attribution(GUI::Painter& painter)
|
void MapWidget::paint_panels(GUI::Painter& painter)
|
||||||
{
|
{
|
||||||
m_attribution_width = PANEL_PADDING_X + painter.font().width(m_attribution_text) + PANEL_PADDING_X;
|
for (auto& panel : m_panels) {
|
||||||
m_attribution_height = PANEL_PADDING_Y + painter.font().pixel_size() + PANEL_PADDING_Y;
|
int panel_width = PANEL_PADDING_X + painter.font().width(panel.text) + PANEL_PADDING_X;
|
||||||
painter.fill_rect({ frame_inner_rect().right() - m_attribution_width, frame_inner_rect().bottom() - m_attribution_height, m_attribution_width, m_attribution_height }, panel_background_color);
|
int panel_height = PANEL_PADDING_Y + painter.font().pixel_size() + PANEL_PADDING_Y;
|
||||||
Gfx::FloatRect attribution_text_rect { 0.0f, 0.0f, frame_inner_rect().right() - PANEL_PADDING_X, frame_inner_rect().bottom() - PANEL_PADDING_Y };
|
if (panel.position == Panel::Position::TopLeft)
|
||||||
painter.draw_text(attribution_text_rect, m_attribution_text, Gfx::TextAlignment::BottomRight, panel_foreground_color);
|
panel.rect = { frame_inner_rect().x(), frame_inner_rect().y(), panel_width, panel_height };
|
||||||
|
if (panel.position == Panel::Position::TopRight)
|
||||||
|
panel.rect = { frame_inner_rect().right() - panel_width, frame_inner_rect().y(), panel_width, panel_height };
|
||||||
|
if (panel.position == Panel::Position::BottomLeft)
|
||||||
|
panel.rect = { frame_inner_rect().x(), frame_inner_rect().bottom() - panel_height, panel_width, panel_height };
|
||||||
|
if (panel.position == Panel::Position::BottomRight)
|
||||||
|
panel.rect = { frame_inner_rect().right() - panel_width, frame_inner_rect().bottom() - panel_height, panel_width, panel_height };
|
||||||
|
painter.fill_rect(panel.rect, panel_background_color);
|
||||||
|
|
||||||
|
Gfx::FloatRect text_rect = { panel.rect.x() + PANEL_PADDING_X, panel.rect.y() + PANEL_PADDING_Y, panel.rect.width(), panel.rect.height() };
|
||||||
|
painter.draw_text(text_rect, panel.text, Gfx::TextAlignment::TopLeft, panel_foreground_color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWidget::paint_event(GUI::PaintEvent& event)
|
void MapWidget::paint_event(GUI::PaintEvent& event)
|
||||||
|
@ -391,6 +403,5 @@ void MapWidget::paint_event(GUI::PaintEvent& event)
|
||||||
paint_tiles(painter);
|
paint_tiles(painter);
|
||||||
if (m_scale_enabled)
|
if (m_scale_enabled)
|
||||||
paint_scale(painter);
|
paint_scale(painter);
|
||||||
if (m_attribution_enabled)
|
paint_panels(painter);
|
||||||
paint_attribution(painter);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,30 @@ public:
|
||||||
int zoom() const { return m_zoom; }
|
int zoom() const { return m_zoom; }
|
||||||
void set_zoom(int zoom);
|
void set_zoom(int zoom);
|
||||||
|
|
||||||
|
struct Panel {
|
||||||
|
enum class Position {
|
||||||
|
TopLeft,
|
||||||
|
TopRight,
|
||||||
|
BottomLeft,
|
||||||
|
BottomRight,
|
||||||
|
};
|
||||||
|
String text;
|
||||||
|
Position position;
|
||||||
|
Optional<URL> url {};
|
||||||
|
bool persistent { false };
|
||||||
|
Gfx::IntRect rect { 0, 0, 0, 0 };
|
||||||
|
};
|
||||||
|
void add_panel(Panel const& panel)
|
||||||
|
{
|
||||||
|
m_panels.append(panel);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
void clear_panels()
|
||||||
|
{
|
||||||
|
m_panels.remove_all_matching([](auto const& panel) { return !panel.persistent; });
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
struct TileKey {
|
struct TileKey {
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
@ -88,7 +112,7 @@ private:
|
||||||
void paint_tiles(GUI::Painter&);
|
void paint_tiles(GUI::Painter&);
|
||||||
void paint_scale_line(GUI::Painter&, String label, Gfx::IntRect rect);
|
void paint_scale_line(GUI::Painter&, String label, Gfx::IntRect rect);
|
||||||
void paint_scale(GUI::Painter&);
|
void paint_scale(GUI::Painter&);
|
||||||
void paint_attribution(GUI::Painter&);
|
void paint_panels(GUI::Painter&);
|
||||||
|
|
||||||
static int constexpr TILE_SIZE = 256;
|
static int constexpr TILE_SIZE = 256;
|
||||||
static double constexpr LATITUDE_MAX = 85.0511287798066;
|
static double constexpr LATITUDE_MAX = 85.0511287798066;
|
||||||
|
@ -96,8 +120,8 @@ private:
|
||||||
static constexpr size_t TILES_DOWNLOAD_PARALLEL_MAX = 8;
|
static constexpr size_t TILES_DOWNLOAD_PARALLEL_MAX = 8;
|
||||||
static int constexpr ZOOM_MIN = 2;
|
static int constexpr ZOOM_MIN = 2;
|
||||||
static int constexpr ZOOM_MAX = 19;
|
static int constexpr ZOOM_MAX = 19;
|
||||||
static float constexpr PANEL_PADDING_X = 6;
|
static int constexpr PANEL_PADDING_X = 6;
|
||||||
static float constexpr PANEL_PADDING_Y = 4;
|
static int constexpr PANEL_PADDING_Y = 4;
|
||||||
|
|
||||||
// These colors match the default OpenStreetMap map tiles style, so they don't depend on any system theme colors
|
// These colors match the default OpenStreetMap map tiles style, so they don't depend on any system theme colors
|
||||||
static Gfx::Color constexpr map_background_color = { 200, 200, 200 };
|
static Gfx::Color constexpr map_background_color = { 200, 200, 200 };
|
||||||
|
@ -113,9 +137,6 @@ private:
|
||||||
bool m_scale_enabled {};
|
bool m_scale_enabled {};
|
||||||
int m_scale_max_width {};
|
int m_scale_max_width {};
|
||||||
bool m_attribution_enabled {};
|
bool m_attribution_enabled {};
|
||||||
String m_attribution_text;
|
|
||||||
float m_attribution_width {};
|
|
||||||
float m_attribution_height {};
|
|
||||||
URL m_attribution_url;
|
URL m_attribution_url;
|
||||||
bool m_dragging { false };
|
bool m_dragging { false };
|
||||||
int m_last_mouse_x { 0 };
|
int m_last_mouse_x { 0 };
|
||||||
|
@ -123,6 +144,7 @@ private:
|
||||||
bool m_first_image_loaded { false };
|
bool m_first_image_loaded { false };
|
||||||
bool m_connection_failed { false };
|
bool m_connection_failed { false };
|
||||||
OrderedHashMap<TileKey, RefPtr<Gfx::Bitmap>> m_tiles;
|
OrderedHashMap<TileKey, RefPtr<Gfx::Bitmap>> m_tiles;
|
||||||
|
Vector<Panel> m_panels;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue