mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:37:35 +00:00
Maps: Add search panel
This commit is contained in:
parent
2c2a1da306
commit
deb7ecfbe9
9 changed files with 331 additions and 22 deletions
|
@ -4,9 +4,13 @@ serenity_component(
|
||||||
TARGETS Maps
|
TARGETS Maps
|
||||||
)
|
)
|
||||||
|
|
||||||
|
compile_gml(SearchPanel.gml SearchPanelGML.cpp)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
MapWidget.cpp
|
MapWidget.cpp
|
||||||
|
SearchPanelGML.cpp
|
||||||
|
SearchPanel.cpp
|
||||||
UsersMapWidget.cpp
|
UsersMapWidget.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
#include <LibGfx/ImageFormats/ImageDecoder.h>
|
||||||
#include <LibProtocol/Request.h>
|
#include <LibProtocol/Request.h>
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
// Math helpers
|
// Math helpers
|
||||||
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Pseudo-code
|
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Pseudo-code
|
||||||
static double longitude_to_tile_x(double longitude, int zoom)
|
static double longitude_to_tile_x(double longitude, int zoom)
|
||||||
|
@ -531,3 +533,5 @@ void MapWidget::paint_event(GUI::PaintEvent& event)
|
||||||
paint_scale(painter);
|
paint_scale(painter);
|
||||||
paint_panels(painter);
|
paint_panels(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include <LibProtocol/Request.h>
|
#include <LibProtocol/Request.h>
|
||||||
#include <LibProtocol/RequestClient.h>
|
#include <LibProtocol/RequestClient.h>
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
class MapWidget : public GUI::Frame
|
class MapWidget : public GUI::Frame
|
||||||
, public Config::Listener {
|
, public Config::Listener {
|
||||||
C_OBJECT(MapWidget);
|
C_OBJECT(MapWidget);
|
||||||
|
@ -63,15 +65,16 @@ public:
|
||||||
LatLng latlng;
|
LatLng latlng;
|
||||||
Optional<String> tooltip {};
|
Optional<String> tooltip {};
|
||||||
RefPtr<Gfx::Bitmap> image { nullptr };
|
RefPtr<Gfx::Bitmap> image { nullptr };
|
||||||
|
Optional<String> name {};
|
||||||
};
|
};
|
||||||
void add_marker(Marker const& marker)
|
void add_marker(Marker const& marker)
|
||||||
{
|
{
|
||||||
m_markers.append(marker);
|
m_markers.append(marker);
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
void clear_markers()
|
void remove_markers_with_name(StringView name)
|
||||||
{
|
{
|
||||||
m_markers.clear();
|
m_markers.remove_all_matching([name](auto const& marker) { return marker.name == name; });
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +188,9 @@ private:
|
||||||
Vector<Panel> m_panels;
|
Vector<Panel> m_panels;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct AK::Traits<MapWidget::TileKey> : public GenericTraits<MapWidget::TileKey> {
|
struct AK::Traits<Maps::MapWidget::TileKey> : public GenericTraits<Maps::MapWidget::TileKey> {
|
||||||
static unsigned hash(MapWidget::TileKey const& t) { return t.hash(); }
|
static unsigned hash(Maps::MapWidget::TileKey const& t) { return t.hash(); }
|
||||||
};
|
};
|
||||||
|
|
132
Userland/Applications/Maps/SearchPanel.cpp
Normal file
132
Userland/Applications/Maps/SearchPanel.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Bastiaan van der Plaat <bastiaan.v.d.plaat@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SearchPanel.h"
|
||||||
|
#include <AK/JsonParser.h>
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<SearchPanel>> SearchPanel::create()
|
||||||
|
{
|
||||||
|
auto widget = TRY(try_create());
|
||||||
|
TRY(widget->setup());
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> SearchPanel::setup()
|
||||||
|
{
|
||||||
|
m_request_client = TRY(Protocol::RequestClient::try_create());
|
||||||
|
|
||||||
|
m_search_textbox = *find_descendant_of_type_named<GUI::TextBox>("search_textbox");
|
||||||
|
m_search_button = *find_descendant_of_type_named<GUI::Button>("search_button");
|
||||||
|
m_start_container = *find_descendant_of_type_named<GUI::Frame>("start_container");
|
||||||
|
m_empty_container = *find_descendant_of_type_named<GUI::Frame>("empty_container");
|
||||||
|
m_places_list = *find_descendant_of_type_named<GUI::ListView>("places_list");
|
||||||
|
|
||||||
|
m_empty_container->set_visible(false);
|
||||||
|
m_places_list->set_visible(false);
|
||||||
|
|
||||||
|
m_search_textbox->on_return_pressed = [this]() {
|
||||||
|
search(MUST(String::from_deprecated_string(m_search_textbox->text())));
|
||||||
|
};
|
||||||
|
m_search_button->on_click = [this](unsigned) {
|
||||||
|
search(MUST(String::from_deprecated_string(m_search_textbox->text())));
|
||||||
|
};
|
||||||
|
|
||||||
|
m_places_list->set_item_height(m_places_list->font().preferred_line_height() * 2 + m_places_list->vertical_padding());
|
||||||
|
m_places_list->on_selection_change = [this]() {
|
||||||
|
auto const& index = m_places_list->selection().first();
|
||||||
|
if (!index.is_valid())
|
||||||
|
return;
|
||||||
|
on_selected_place_change(m_places.at(index.row()));
|
||||||
|
};
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPanel::search(StringView query)
|
||||||
|
{
|
||||||
|
// Show start container when empty query
|
||||||
|
if (query.is_empty()) {
|
||||||
|
m_start_container->set_visible(true);
|
||||||
|
m_empty_container->set_visible(false);
|
||||||
|
m_places_list->set_visible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_start_container->set_visible(false);
|
||||||
|
|
||||||
|
// Start HTTP GET request to load people.json
|
||||||
|
HashMap<DeprecatedString, DeprecatedString> headers;
|
||||||
|
headers.set("User-Agent", "SerenityOS Maps");
|
||||||
|
headers.set("Accept", "application/json");
|
||||||
|
URL url(MUST(String::formatted("https://nominatim.openstreetmap.org/search?q={}&format=json", AK::URL::percent_encode(query, AK::URL::PercentEncodeSet::Query))));
|
||||||
|
auto request = m_request_client->start_request("GET", url, headers, {});
|
||||||
|
VERIFY(!request.is_null());
|
||||||
|
m_request = request;
|
||||||
|
request->on_buffered_request_finish = [this, request, url](bool success, auto, auto&, auto, ReadonlyBytes payload) {
|
||||||
|
m_request.clear();
|
||||||
|
if (!success) {
|
||||||
|
dbgln("Maps: Can't load: {}", url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse JSON data
|
||||||
|
JsonParser parser(payload);
|
||||||
|
auto result = parser.parse();
|
||||||
|
if (result.is_error()) {
|
||||||
|
dbgln("Maps: Can't parse JSON: {}", url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show empty label when no places are found
|
||||||
|
auto json_places = result.release_value().as_array();
|
||||||
|
if (json_places.size() == 0) {
|
||||||
|
m_empty_container->set_visible(true);
|
||||||
|
m_places_list->set_visible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse places from JSON data
|
||||||
|
m_places.clear();
|
||||||
|
m_places_names.clear();
|
||||||
|
for (size_t i = 0; i < json_places.size(); i++) {
|
||||||
|
// FIXME: Handle JSON parsing errors
|
||||||
|
auto const& json_place = json_places.at(i).as_object();
|
||||||
|
|
||||||
|
String name = MUST(String::from_deprecated_string(json_place.get_deprecated_string("display_name"sv).release_value()));
|
||||||
|
MapWidget::LatLng latlng = { json_place.get_deprecated_string("lat"sv).release_value().to_double().release_value(),
|
||||||
|
json_place.get_deprecated_string("lon"sv).release_value().to_double().release_value() };
|
||||||
|
|
||||||
|
// Calculate the right zoom level for bounding box
|
||||||
|
auto const& json_boundingbox = json_place.get_array("boundingbox"sv);
|
||||||
|
MapWidget::LatLngBounds bounds = {
|
||||||
|
{ json_boundingbox->at(0).as_string().to_double().release_value(),
|
||||||
|
json_boundingbox->at(2).as_string().to_double().release_value() },
|
||||||
|
{ json_boundingbox->at(1).as_string().to_double().release_value(),
|
||||||
|
json_boundingbox->at(3).as_string().to_double().release_value() }
|
||||||
|
};
|
||||||
|
|
||||||
|
m_places.append({ name, latlng, bounds.get_zoom() });
|
||||||
|
m_places_names.append(MUST(String::formatted("{}\n{:.5}, {:.5}", name, latlng.latitude, latlng.longitude)));
|
||||||
|
}
|
||||||
|
on_places_change(m_places);
|
||||||
|
|
||||||
|
// Update and show places list
|
||||||
|
m_empty_container->set_visible(false);
|
||||||
|
m_places_list->set_model(*GUI::ItemListModel<String>::create(m_places_names));
|
||||||
|
m_places_list->set_visible(true);
|
||||||
|
};
|
||||||
|
request->set_should_buffer_all_input(true);
|
||||||
|
request->on_certificate_requested = []() -> Protocol::Request::CertificateAndKey { return {}; };
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchPanel::reset()
|
||||||
|
{
|
||||||
|
m_search_textbox->set_text(""sv);
|
||||||
|
search(""sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
Userland/Applications/Maps/SearchPanel.gml
Normal file
63
Userland/Applications/Maps/SearchPanel.gml
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
@Maps::SearchPanel {
|
||||||
|
min_width: 100
|
||||||
|
preferred_width: 200
|
||||||
|
max_width: 350
|
||||||
|
layout: @GUI::VerticalBoxLayout {
|
||||||
|
spacing: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Frame {
|
||||||
|
frame_style: "SunkenPanel"
|
||||||
|
fixed_height: 28
|
||||||
|
layout: @GUI::HorizontalBoxLayout {
|
||||||
|
margins: [2]
|
||||||
|
spacing: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::TextBox {
|
||||||
|
name: "search_textbox"
|
||||||
|
placeholder: "Search a place..."
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Button {
|
||||||
|
name: "search_button"
|
||||||
|
icon_from_path: "/res/icons/16x16/find.png"
|
||||||
|
fixed_width: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start, empty and places are toggled in visibility
|
||||||
|
@GUI::Frame {
|
||||||
|
name: "start_container"
|
||||||
|
frame_style: "SunkenPanel"
|
||||||
|
layout: @GUI::VerticalBoxLayout {
|
||||||
|
margins: [4]
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Label {
|
||||||
|
text: "Enter a search query to search for places..."
|
||||||
|
text_alignment: "CenterLeft"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Frame {
|
||||||
|
name: "empty_container"
|
||||||
|
frame_style: "SunkenPanel"
|
||||||
|
layout: @GUI::VerticalBoxLayout {
|
||||||
|
margins: [4]
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::Label {
|
||||||
|
text: "Can't find any places with the search query"
|
||||||
|
text_alignment: "CenterLeft"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GUI::ListView {
|
||||||
|
name: "places_list"
|
||||||
|
horizontal_padding: 6
|
||||||
|
vertical_padding: 4
|
||||||
|
should_hide_unnecessary_scrollbars: true
|
||||||
|
alternating_row_colors: false
|
||||||
|
}
|
||||||
|
}
|
55
Userland/Applications/Maps/SearchPanel.h
Normal file
55
Userland/Applications/Maps/SearchPanel.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Bastiaan van der Plaat <bastiaan.v.d.plaat@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MapWidget.h"
|
||||||
|
#include <LibGUI/Button.h>
|
||||||
|
#include <LibGUI/Frame.h>
|
||||||
|
#include <LibGUI/ItemListModel.h>
|
||||||
|
#include <LibGUI/ListView.h>
|
||||||
|
#include <LibGUI/TextBox.h>
|
||||||
|
#include <LibProtocol/Request.h>
|
||||||
|
#include <LibProtocol/RequestClient.h>
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
|
class SearchPanel final : public GUI::Widget {
|
||||||
|
C_OBJECT(SearchPanel)
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ErrorOr<NonnullRefPtr<SearchPanel>> create();
|
||||||
|
|
||||||
|
void search(StringView query);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
struct Place {
|
||||||
|
String name;
|
||||||
|
MapWidget::LatLng latlng;
|
||||||
|
int zoom;
|
||||||
|
};
|
||||||
|
Function<void(Vector<Place> const&)> on_places_change;
|
||||||
|
Function<void(Place const&)> on_selected_place_change;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SearchPanel() = default;
|
||||||
|
static ErrorOr<NonnullRefPtr<SearchPanel>> try_create();
|
||||||
|
|
||||||
|
ErrorOr<void> setup();
|
||||||
|
|
||||||
|
RefPtr<Protocol::RequestClient> m_request_client;
|
||||||
|
RefPtr<Protocol::Request> m_request;
|
||||||
|
RefPtr<GUI::TextBox> m_search_textbox;
|
||||||
|
RefPtr<GUI::Button> m_search_button;
|
||||||
|
RefPtr<GUI::Frame> m_start_container;
|
||||||
|
RefPtr<GUI::Frame> m_empty_container;
|
||||||
|
RefPtr<GUI::ListView> m_places_list;
|
||||||
|
RefPtr<GUI::ItemListModel<String>> m_places_names_model;
|
||||||
|
Vector<Place> m_places;
|
||||||
|
Vector<String> m_places_names;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,8 @@
|
||||||
#include <AK/JsonParser.h>
|
#include <AK/JsonParser.h>
|
||||||
#include <LibDesktop/Launcher.h>
|
#include <LibDesktop/Launcher.h>
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
UsersMapWidget::UsersMapWidget(Options const& options)
|
UsersMapWidget::UsersMapWidget(Options const& options)
|
||||||
: MapWidget::MapWidget(options)
|
: MapWidget::MapWidget(options)
|
||||||
{
|
{
|
||||||
|
@ -65,7 +67,7 @@ void UsersMapWidget::add_users_to_map()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto const& user : m_users.value()) {
|
for (auto const& user : m_users.value()) {
|
||||||
MapWidget::Marker marker = { user.coordinates, user.nick };
|
MapWidget::Marker marker = { user.coordinates, user.nick, {}, "users"_string };
|
||||||
if (!user.contributor)
|
if (!user.contributor)
|
||||||
marker.image = m_marker_gray_image;
|
marker.image = m_marker_gray_image;
|
||||||
add_marker(marker);
|
add_marker(marker);
|
||||||
|
@ -76,3 +78,5 @@ void UsersMapWidget::add_users_to_map()
|
||||||
{ { "https://github.com/SerenityOS/user-map" } },
|
{ { "https://github.com/SerenityOS/user-map" } },
|
||||||
"users"_string });
|
"users"_string });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "MapWidget.h"
|
#include "MapWidget.h"
|
||||||
|
|
||||||
|
namespace Maps {
|
||||||
|
|
||||||
class UsersMapWidget final : public MapWidget {
|
class UsersMapWidget final : public MapWidget {
|
||||||
C_OBJECT(UsersMapWidget);
|
C_OBJECT(UsersMapWidget);
|
||||||
|
|
||||||
|
@ -23,7 +25,7 @@ public:
|
||||||
add_users_to_map();
|
add_users_to_map();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clear_markers();
|
remove_markers_with_name("users"sv);
|
||||||
remove_panels_with_name("users"sv);
|
remove_panels_with_name("users"sv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,3 +48,5 @@ private:
|
||||||
};
|
};
|
||||||
Optional<Vector<User>> m_users;
|
Optional<Vector<User>> m_users;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "SearchPanel.h"
|
||||||
#include "UsersMapWidget.h"
|
#include "UsersMapWidget.h"
|
||||||
#include <LibConfig/Client.h>
|
#include <LibConfig/Client.h>
|
||||||
#include <LibCore/System.h>
|
#include <LibCore/System.h>
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include <LibGUI/Icon.h>
|
#include <LibGUI/Icon.h>
|
||||||
#include <LibGUI/Menu.h>
|
#include <LibGUI/Menu.h>
|
||||||
#include <LibGUI/Process.h>
|
#include <LibGUI/Process.h>
|
||||||
|
#include <LibGUI/Splitter.h>
|
||||||
#include <LibGUI/ToolbarContainer.h>
|
#include <LibGUI/ToolbarContainer.h>
|
||||||
#include <LibGUI/Window.h>
|
#include <LibGUI/Window.h>
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
Config::monitor_domain("Maps");
|
Config::monitor_domain("Maps");
|
||||||
|
|
||||||
|
// Window
|
||||||
auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-maps"sv));
|
auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-maps"sv));
|
||||||
auto window = GUI::Window::construct();
|
auto window = GUI::Window::construct();
|
||||||
window->set_title("Maps");
|
window->set_title("Maps");
|
||||||
|
@ -49,14 +52,32 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
auto toolbar_container = TRY(root_widget->try_add<GUI::ToolbarContainer>());
|
auto toolbar_container = TRY(root_widget->try_add<GUI::ToolbarContainer>());
|
||||||
auto toolbar = TRY(toolbar_container->try_add<GUI::Toolbar>());
|
auto toolbar = TRY(toolbar_container->try_add<GUI::Toolbar>());
|
||||||
|
|
||||||
|
// Main Widget
|
||||||
|
auto main_widget = TRY(root_widget->try_add<GUI::HorizontalSplitter>());
|
||||||
|
|
||||||
// Map widget
|
// Map widget
|
||||||
UsersMapWidget::Options options {};
|
Maps::UsersMapWidget::Options options {};
|
||||||
options.center.latitude = Config::read_string("Maps"sv, "MapView"sv, "CenterLatitude"sv, "30"sv).to_double().value_or(30.0);
|
options.center.latitude = Config::read_string("Maps"sv, "MapView"sv, "CenterLatitude"sv, "30"sv).to_double().value_or(30.0);
|
||||||
options.center.longitude = Config::read_string("Maps"sv, "MapView"sv, "CenterLongitude"sv, "0"sv).to_double().value_or(0.0);
|
options.center.longitude = Config::read_string("Maps"sv, "MapView"sv, "CenterLongitude"sv, "0"sv).to_double().value_or(0.0);
|
||||||
options.zoom = Config::read_i32("Maps"sv, "MapView"sv, "Zoom"sv, MAP_ZOOM_DEFAULT);
|
options.zoom = Config::read_i32("Maps"sv, "MapView"sv, "Zoom"sv, MAP_ZOOM_DEFAULT);
|
||||||
auto maps = TRY(root_widget->try_add<UsersMapWidget>(options));
|
auto map_widget = TRY(main_widget->try_add<Maps::UsersMapWidget>(options));
|
||||||
maps->set_frame_style(Gfx::FrameStyle::SunkenContainer);
|
map_widget->set_frame_style(Gfx::FrameStyle::SunkenContainer);
|
||||||
maps->set_show_users(Config::read_bool("Maps"sv, "MapView"sv, "ShowUsers"sv, false));
|
map_widget->set_show_users(Config::read_bool("Maps"sv, "MapView"sv, "ShowUsers"sv, false));
|
||||||
|
|
||||||
|
// Search panel
|
||||||
|
auto search_panel = TRY(Maps::SearchPanel::create());
|
||||||
|
search_panel->on_places_change = [map_widget](auto) { map_widget->remove_markers_with_name("search"sv); };
|
||||||
|
search_panel->on_selected_place_change = [map_widget](auto const& place) {
|
||||||
|
// Remove old search markers
|
||||||
|
map_widget->remove_markers_with_name("search"sv);
|
||||||
|
|
||||||
|
// Add new marker and zoom into it
|
||||||
|
map_widget->add_marker({ place.latlng, place.name, {}, "search"_string });
|
||||||
|
map_widget->set_center(place.latlng);
|
||||||
|
map_widget->set_zoom(place.zoom);
|
||||||
|
};
|
||||||
|
if (Config::read_bool("Maps"sv, "SearchPanel"sv, "Show"sv, false))
|
||||||
|
main_widget->insert_child_before(search_panel, map_widget);
|
||||||
|
|
||||||
// Main menu actions
|
// Main menu actions
|
||||||
auto file_menu = window->add_menu("&File"_string);
|
auto file_menu = window->add_menu("&File"_string);
|
||||||
|
@ -68,18 +89,32 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
file_menu->add_action(GUI::CommonActions::make_quit_action([](auto&) { GUI::Application::the()->quit(); }));
|
file_menu->add_action(GUI::CommonActions::make_quit_action([](auto&) { GUI::Application::the()->quit(); }));
|
||||||
|
|
||||||
auto view_menu = window->add_menu("&View"_string);
|
auto view_menu = window->add_menu("&View"_string);
|
||||||
|
auto show_search_panel_action = GUI::Action::create_checkable(
|
||||||
|
"Show search panel", TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"sv)), [main_widget, search_panel, map_widget](auto& action) {
|
||||||
|
if (action.is_checked()) {
|
||||||
|
main_widget->insert_child_before(search_panel, map_widget);
|
||||||
|
} else {
|
||||||
|
map_widget->remove_markers_with_name("search"sv);
|
||||||
|
search_panel->reset();
|
||||||
|
main_widget->remove_child(search_panel);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
window);
|
||||||
|
show_search_panel_action->set_checked(Config::read_bool("Maps"sv, "SearchPanel"sv, "Show"sv, false));
|
||||||
auto show_users_action = GUI::Action::create_checkable(
|
auto show_users_action = GUI::Action::create_checkable(
|
||||||
"Show SerenityOS users", TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/ladyball.png"sv)), [maps](auto& action) { maps->set_show_users(action.is_checked()); }, window);
|
"Show SerenityOS users", TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/ladyball.png"sv)), [map_widget](auto& action) { map_widget->set_show_users(action.is_checked()); }, window);
|
||||||
show_users_action->set_checked(maps->show_users());
|
show_users_action->set_checked(map_widget->show_users());
|
||||||
auto zoom_in_action = GUI::CommonActions::make_zoom_in_action([maps](auto&) { maps->set_zoom(maps->zoom() + 1); }, window);
|
auto zoom_in_action = GUI::CommonActions::make_zoom_in_action([map_widget](auto&) { map_widget->set_zoom(map_widget->zoom() + 1); }, window);
|
||||||
auto zoom_out_action = GUI::CommonActions::make_zoom_out_action([maps](auto&) { maps->set_zoom(maps->zoom() - 1); }, window);
|
auto zoom_out_action = GUI::CommonActions::make_zoom_out_action([map_widget](auto&) { map_widget->set_zoom(map_widget->zoom() - 1); }, window);
|
||||||
auto reset_zoom_action = GUI::CommonActions::make_reset_zoom_action([maps](auto&) { maps->set_zoom(MAP_ZOOM_DEFAULT); }, window);
|
auto reset_zoom_action = GUI::CommonActions::make_reset_zoom_action([map_widget](auto&) { map_widget->set_zoom(MAP_ZOOM_DEFAULT); }, window);
|
||||||
auto fullscreen_action = GUI::CommonActions::make_fullscreen_action([window, toolbar_container, maps](auto&) {
|
auto fullscreen_action = GUI::CommonActions::make_fullscreen_action([window, toolbar_container, map_widget](auto&) {
|
||||||
window->set_fullscreen(!window->is_fullscreen());
|
window->set_fullscreen(!window->is_fullscreen());
|
||||||
toolbar_container->set_visible(!window->is_fullscreen());
|
toolbar_container->set_visible(!window->is_fullscreen());
|
||||||
maps->set_frame_style(window->is_fullscreen() ? Gfx::FrameStyle::NoFrame : Gfx::FrameStyle::SunkenContainer);
|
map_widget->set_frame_style(window->is_fullscreen() ? Gfx::FrameStyle::NoFrame : Gfx::FrameStyle::SunkenContainer);
|
||||||
},
|
},
|
||||||
window);
|
window);
|
||||||
|
view_menu->add_action(show_search_panel_action);
|
||||||
|
view_menu->add_separator();
|
||||||
view_menu->add_action(show_users_action);
|
view_menu->add_action(show_users_action);
|
||||||
view_menu->add_separator();
|
view_menu->add_separator();
|
||||||
view_menu->add_action(zoom_in_action);
|
view_menu->add_action(zoom_in_action);
|
||||||
|
@ -93,6 +128,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
help_menu->add_action(GUI::CommonActions::make_about_action("Maps"_string, app_icon, window));
|
help_menu->add_action(GUI::CommonActions::make_about_action("Maps"_string, app_icon, window));
|
||||||
|
|
||||||
// Main toolbar actions
|
// Main toolbar actions
|
||||||
|
toolbar->add_action(show_search_panel_action);
|
||||||
|
toolbar->add_separator();
|
||||||
toolbar->add_action(show_users_action);
|
toolbar->add_action(show_users_action);
|
||||||
toolbar->add_separator();
|
toolbar->add_separator();
|
||||||
toolbar->add_action(zoom_in_action);
|
toolbar->add_action(zoom_in_action);
|
||||||
|
@ -103,11 +140,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||||
|
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
// Remember last map position
|
// Remember last window state
|
||||||
int exec = app->exec();
|
int exec = app->exec();
|
||||||
Config::write_string("Maps"sv, "MapView"sv, "CenterLatitude"sv, TRY(String::number(maps->center().latitude)));
|
Config::write_bool("Maps"sv, "SearchPanel"sv, "Show"sv, show_search_panel_action->is_checked());
|
||||||
Config::write_string("Maps"sv, "MapView"sv, "CenterLongitude"sv, TRY(String::number(maps->center().longitude)));
|
Config::write_string("Maps"sv, "MapView"sv, "CenterLatitude"sv, TRY(String::number(map_widget->center().latitude)));
|
||||||
Config::write_i32("Maps"sv, "MapView"sv, "Zoom"sv, maps->zoom());
|
Config::write_string("Maps"sv, "MapView"sv, "CenterLongitude"sv, TRY(String::number(map_widget->center().longitude)));
|
||||||
Config::write_bool("Maps"sv, "MapView"sv, "ShowUsers"sv, maps->show_users());
|
Config::write_i32("Maps"sv, "MapView"sv, "Zoom"sv, map_widget->zoom());
|
||||||
|
Config::write_bool("Maps"sv, "MapView"sv, "ShowUsers"sv, map_widget->show_users());
|
||||||
return exec;
|
return exec;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue