/* * 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 "ui_font_fixed_8x16.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(); 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: * ' \"", Color::light_grey() }, // No ° symbol in 8x16 font { { 1 * 8, 2 * 16 }, "Lon: * ' \"", 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 init(); void set_mode(GeoMapMode mode); 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); private: 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() ); GeoMapMode mode_ { }; File map_file { }; uint16_t map_width { }, map_height { }; int32_t map_center_x { }, map_center_y { }; 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_ { }; 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 { }; const Dim banner_height = 3 * 16; 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, banner_height, 240, 320 - 16 - banner_height } }; Button button_ok { { 20 * 8, 8, 8 * 8, 2 * 16 }, "OK" }; }; } /* namespace ui */ #endif