/* * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. * Copyright (C) 2017 Furrtek * * This file is part of PortaPack. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef __GEOMAP_H__ #define __GEOMAP_H__ #include "ui.hpp" #include "file.hpp" #include "ui_navigation.hpp" #include "portapack.hpp" namespace ui { enum GeoMapMode { DISPLAY, PROMPT }; struct GeoMarker { public: float lat{0}; float lon{0}; uint16_t angle{0}; std::string tag{""}; GeoMarker& operator=(GeoMarker& rhs) { lat = rhs.lat; lon = rhs.lon; angle = rhs.angle; tag = rhs.tag; return *this; } }; class GeoPos : public View { public: enum alt_unit { FEET = 0, METERS }; std::function on_change{}; GeoPos(const Point pos, const alt_unit altitude_unit); void focus() override; void set_read_only(bool v); void set_altitude(int32_t altitude); void set_lat(float lat); void set_lon(float lon); int32_t altitude(); void hide_altitude(); float lat(); float lon(); void set_report_change(bool v); private: bool read_only{false}; bool report_change{true}; alt_unit altitude_unit_{}; Labels labels_position{ {{1 * 8, 0 * 16}, "Alt:", Color::light_grey()}, {{1 * 8, 1 * 16}, "Lat: \xB0 ' \"", Color::light_grey()}, // 0xB0 is degree ° symbol in our 8x16 font {{1 * 8, 2 * 16}, "Lon: \xB0 ' \"", Color::light_grey()}, }; NumberField field_altitude{ {6 * 8, 0 * 16}, 5, {-1000, 50000}, 250, ' '}; Text text_alt_unit{ {12 * 8, 0 * 16, 2 * 8, 16}, ""}; NumberField field_lat_degrees{ {5 * 8, 1 * 16}, 4, {-90, 90}, 1, ' '}; NumberField field_lat_minutes{ {10 * 8, 1 * 16}, 2, {0, 59}, 1, ' '}; NumberField field_lat_seconds{ {13 * 8, 1 * 16}, 2, {0, 59}, 1, ' '}; Text text_lat_decimal{ {17 * 8, 1 * 16, 13 * 8, 1 * 16}, ""}; NumberField field_lon_degrees{ {5 * 8, 2 * 16}, 4, {-180, 180}, 1, ' '}; NumberField field_lon_minutes{ {10 * 8, 2 * 16}, 2, {0, 59}, 1, ' '}; NumberField field_lon_seconds{ {13 * 8, 2 * 16}, 2, {0, 59}, 1, ' '}; Text text_lon_decimal{ {17 * 8, 2 * 16, 13 * 8, 1 * 16}, ""}; }; enum MapMarkerStored { MARKER_NOT_STORED, MARKER_STORED, MARKER_LIST_FULL }; class GeoMap : public Widget { public: std::function on_move{}; GeoMap(Rect parent_rect); void paint(Painter& painter) override; bool on_touch(const TouchEvent event) override; bool on_encoder(const EncoderEvent delta) override; bool init(); void set_mode(GeoMapMode mode); void set_manual_panning(bool v); bool manual_panning(); void move(const float lon, const float lat); void set_tag(std::string new_tag) { tag_ = new_tag; } void set_angle(uint16_t new_angle) { angle_ = new_angle; } static const int NumMarkerListElements = 30; void clear_markers(); MapMarkerStored store_marker(GeoMarker& marker); static const Dim banner_height = 3 * 16; static const Dim geomap_rect_width = 240; static const Dim geomap_rect_height = 320 - 16 - banner_height; private: void draw_scale(Painter& painter); void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color); void draw_marker(Painter& painter, const ui::Point itemPoint, const uint16_t itemAngle, const std::string itemTag, const Color color = Color::red(), const Color fontColor = Color::white(), const Color backColor = Color::black()); void draw_markers(Painter& painter); void map_zoom_line(ui::Color* buffer); bool manual_panning_{false}; GeoMapMode mode_{}; File map_file{}; uint16_t map_width{}, map_height{}; int32_t map_center_x{}, map_center_y{}; int16_t map_zoom{1}; float lon_ratio{}, lat_ratio{}; double map_bottom{}; double map_world_lon{}; double map_offset{}; int32_t x_pos{}, y_pos{}; int32_t prev_x_pos{0xFFFF}, prev_y_pos{0xFFFF}; float lat_{}; float lon_{}; float pixels_per_km{}; uint16_t angle_{}; std::string tag_{}; int markerListLen{0}; GeoMarker markerList[NumMarkerListElements]; bool markerListUpdated{false}; }; class GeoMapView : public View { public: GeoMapView( NavigationView& nav, const std::string& tag, int32_t altitude, GeoPos::alt_unit altitude_unit, float lat, float lon, uint16_t angle, const std::function on_close = nullptr); GeoMapView(NavigationView& nav, int32_t altitude, GeoPos::alt_unit altitude_unit, float lat, float lon, const std::function on_done); ~GeoMapView(); GeoMapView(const GeoMapView&) = delete; GeoMapView(GeoMapView&&) = delete; GeoMapView& operator=(const GeoMapView&) = delete; GeoMapView& operator=(GeoMapView&&) = delete; void focus() override; void update_position(float lat, float lon, uint16_t angle, int32_t altitude); std::string title() const override { return "Map view"; }; void clear_markers(); MapMarkerStored store_marker(GeoMarker& marker); void update_tag(const std::string tag); private: NavigationView& nav_; void setup(); const std::function on_done{}; GeoMapMode mode_{}; int32_t altitude_{}; GeoPos::alt_unit altitude_unit_{}; float lat_{}; float lon_{}; uint16_t angle_{}; std::function on_close_{nullptr}; bool map_opened{}; GeoPos geopos{ {0, 0}, altitude_unit_}; GeoMap geomap{ {0, GeoMap::banner_height, GeoMap::geomap_rect_width, GeoMap::geomap_rect_height}}; Button button_ok{ {20 * 8, 8, 8 * 8, 2 * 16}, "OK"}; }; } /* namespace ui */ #endif