49#include <wx/aui/aui.h>
54#include <wx/printdlg.h>
56#include <wx/statline.h>
57#include <wx/stdpaths.h>
59#include "libgui/button_switch.h"
71#if wxCHECK_VERSION(3, 2, 0)
72#define _(s) wxGetTranslation(wxASCII_STR(s)).ToStdString()
74#define _(s) wxGetTranslation((s)).ToStdString()
79static const std::unordered_map<RoutePrintOptions, std::string> kLabelByOption =
80 {{RoutePrintOptions::kWaypointName, _(
"Waypoint")},
81 {RoutePrintOptions::kWaypointPosition, _(
"Position")},
82 {RoutePrintOptions::kWaypointCourse, _(
"Course")},
83 {RoutePrintOptions::kWaypointDistance, _(
"Distance")},
84 {RoutePrintOptions::kWaypointDescription, _(
"Description")},
85 {RoutePrintOptions::kWaypointSpeed, _(
"Speed")},
86 {RoutePrintOptions::kWaypointETA, _(
"ETA")},
87 {RoutePrintOptions::kWaypointETD, _(
"ETD")},
88 {RoutePrintOptions::kWaypointTideEvent, _(
"Next tide event")}};
92class ButtonSizer :
public wxStdDialogButtonSizer {
94 explicit ButtonSizer(wxWindow* parent) : wxStdDialogButtonSizer() {
95 auto ok_btn =
new wxButton(parent, wxID_OK, _(
"Print..."));
97 AddButton(
new wxButton(parent, wxID_CANCEL));
98 SetAffirmativeButton(ok_btn);
105RoutePrintDlg::RoutePrintDlg(wxWindow* parent)
106 : wxDialog(parent, wxID_ANY, _(
"Print route")) {
107 auto flags = wxSizerFlags().Border();
108 auto grid =
new wxFlexGridSizer(2);
109 for (
auto& [option, label] : kLabelByOption) {
110 grid->Add(
new wxStaticText(
this, wxID_ANY, label), flags.Expand());
111 int id = wxWindow::NewControlId();
113 IdByOption[option] = id;
115 auto vbox =
new wxBoxSizer(wxVERTICAL);
116 vbox->Add(grid, wxSizerFlags().Expand().Border());
117 vbox->Add(
new wxStaticLine(
this, wxID_ANY), flags.Expand());
118 vbox->Add(
new ButtonSizer(
this), flags.Expand());
122 Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent&) { Destroy(); });
125bool RoutePrintDlg::IsEnabled(RoutePrintOptions option)
const {
126 auto found = IdByOption.find(option);
127 assert(found != IdByOption.end() &&
"Illegal option");
130 id = IdByOption.at(option);
131 }
catch (std::out_of_range&) {
134 assert(btn &&
"Could not look up button");
139 const int tz_selection)
145 m_table.StartFillHeader();
149 if (dlg.IsEnabled(RoutePrintOptions::kWaypointName)) {
150 m_table << _(
"Waypoint");
152 if (dlg.IsEnabled(RoutePrintOptions::kWaypointPosition)) {
153 m_table << _(
"Position");
155 if (dlg.IsEnabled(RoutePrintOptions::kWaypointCourse)) {
156 m_table << _(
"Course");
158 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDistance)) {
159 m_table << _(
"Distance");
161 if (dlg.IsEnabled(RoutePrintOptions::kWaypointSpeed)) {
162 m_table << _(
"Speed");
164 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETA)) {
167 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETD)) {
170 if (dlg.IsEnabled(RoutePrintOptions::kWaypointTideEvent)) {
171 m_table << _(
"Next tide event");
173 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDescription)) {
174 m_table << _(
"Description");
178 m_table.StartFillWidths();
181 if (dlg.IsEnabled(RoutePrintOptions::kWaypointName)) {
184 if (dlg.IsEnabled(RoutePrintOptions::kWaypointPosition)) {
187 if (dlg.IsEnabled(RoutePrintOptions::kWaypointCourse)) {
190 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDistance)) {
193 if (dlg.IsEnabled(RoutePrintOptions::kWaypointSpeed)) {
196 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETA)) {
199 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETD)) {
202 if (dlg.IsEnabled(RoutePrintOptions::kWaypointTideEvent)) {
205 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDescription)) {
209 m_table.StartFillData();
211 for (
int n = 1; n <= m_route->GetnPoints(); n++) {
213 if (NULL == point)
continue;
221 if (dlg.IsEnabled(RoutePrintOptions::kWaypointName)) {
222 m_table << point->GetName();
224 if (dlg.IsEnabled(RoutePrintOptions::kWaypointPosition)) {
225 std::wostringstream point_position;
226 point_position << toSDMM(1, point->m_lat,
false) <<
"\n"
227 << toSDMM(2, point->m_lon,
false);
228 m_table << point_position.str();
230 if (dlg.IsEnabled(RoutePrintOptions::kWaypointCourse)) {
232 m_table << formatAngle(point->GetCourse());
237 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDistance)) {
239 std::ostringstream point_distance;
240 point_distance << std::fixed << std::setprecision(2) << std::setw(6)
242 << getUsrDistanceUnit();
243 m_table << point_distance.str();
248 if (dlg.IsEnabled(RoutePrintOptions::kWaypointSpeed)) {
249 std::wostringstream point_speed;
251 point_speed << std::fixed << std::setprecision(1);
257 point_speed << getUsrSpeedUnit().ToStdString();
258 m_table << point_speed.str();
263 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETA)) {
265 .FormatISOCombined(
' ');
267 if (dlg.IsEnabled(RoutePrintOptions::kWaypointETD)) {
271 .FormatISOCombined(
' ');
276 if (dlg.IsEnabled(RoutePrintOptions::kWaypointTideEvent)) {
277 std::wostringstream point_tide;
279 int station_id =
ptcmgr->GetStationIDXbyName(
281 if (station_id > 0) {
282 point_tide <<
ptcmgr->GetTidalEventStr(station_id, point->
GetETA(),
283 point->m_lat, point->m_lon,
286 m_table << point_tide.str();
294 if (dlg.IsEnabled(RoutePrintOptions::kWaypointDescription)) {
295 m_table << point->GetDescription();
301void RoutePrintout::OnPreparePrinting() {
303 wxFont routePrintFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
304 wxFONTWEIGHT_NORMAL);
305 dc->SetFont(routePrintFont);
314 int max_x = wxMin(w, 1000);
315 int max_y = wxMin(h, 1000);
318 double scale_x = (double)(w / max_x);
319 double scale_y = (double)(h / max_y);
322 double actual_scale = wxMin(scale_x, scale_y);
325 dc->SetUserScale(actual_scale, actual_scale);
326 dc->SetDeviceOrigin((
long)m_margin_x, (
long)m_margin_y);
328 m_table.AdjustCells(dc, m_margin_x, m_margin_y);
329 m_pages = m_table.GetNumberPages();
333 wxFont title_font(16, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
335 wxFont subtitle_font(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
336 wxFONTWEIGHT_NORMAL);
337 wxFont header_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
339 wxFont normal_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
340 wxFONTWEIGHT_NORMAL);
342 wxBrush brush(wxColour(255, 255, 255), wxBRUSHSTYLE_TRANSPARENT);
345 int current_x = m_margin_x;
346 int current_y = m_margin_y;
348 std::wostringstream title;
349 std::wostringstream subtitle;
350 std::wostringstream distance;
352 distance << std::fixed << std::setprecision(1)
354 << getUsrDistanceUnit().ToStdString();
358 title <<
" (" << distance.str() <<
")";
360 title << _(
"Total distance ") << distance.str();
372 int title_width, title_height;
373 dc->SetFont(title_font);
374 dc->GetTextExtent(title.str(), &title_width, &title_height);
375 dc->DrawText(title.str(), current_x, current_y);
376 current_y += title_height + m_text_offset_y;
378 if (subtitle.str().length() > 0) {
379 int subtitle_width, subtitle_height;
380 dc->SetFont(subtitle_font);
381 dc->GetTextExtent(subtitle.str(), &subtitle_width, &subtitle_height);
382 dc->DrawText(subtitle.str(), current_x, current_y);
383 current_y += subtitle_height + m_text_offset_y;
386 dc->SetFont(normal_font);
390 int page_size_x, page_size_y;
391 dc->GetSize(&page_size_x, &page_size_y);
395 dc->DrawText(cell_desc.GetText(), current_x, current_y);
396 current_y += cell_desc.GetHeight() + m_text_offset_y;
399 vector<PrintCell>& header_content = m_table.GetHeader();
400 for (
size_t j = 0; j < header_content.size(); j++) {
402 dc->DrawRectangle(current_x, current_y, cell.GetWidth() + m_text_offset_x,
403 cell.GetHeight() + m_text_offset_y);
404 dc->DrawText(cell.GetText(), current_x + m_text_offset_x,
405 current_y + m_text_offset_y);
406 current_x += cell.GetWidth() + m_text_offset_x;
409 wxFont routePrintFont_normal(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
410 wxFONTWEIGHT_NORMAL);
411 dc->SetFont(routePrintFont_normal);
413 vector<vector<PrintCell>>& cells = m_table.GetContent();
414 current_y += m_table.GetHeaderHeight() + m_text_offset_y;
415 int current_height = 0;
416 for (
size_t i = 0; i < cells.size(); i++) {
417 vector<PrintCell>& content_row = cells[i];
418 current_x = m_margin_x;
419 for (
size_t j = 0; j < content_row.size(); j++) {
421 if (cell.GetPage() == page) {
422 wxRect r(current_x, current_y, cell.GetWidth() + m_text_offset_x,
423 cell.GetHeight() + m_text_offset_y);
424 dc->DrawRectangle(r);
425 r.Offset(m_text_offset_x, m_text_offset_y);
426 dc->DrawLabel(cell.GetText(), r);
427 current_x += cell.GetWidth() + m_text_offset_x;
428 current_height = cell.GetHeight() + m_text_offset_y;
431 current_y += current_height;
This class takes multilined string and modifies it to fit into given width for given device.
Represents a waypoint or mark within the navigation system.
wxDateTime GetManualETD()
Retrieves the manually set Estimated Time of Departure for this waypoint, in UTC.
double GetPlannedSpeed()
Return the planned speed associated with this waypoint.
wxString m_TideStation
Associated tide station identifier.
wxDateTime GetETA()
Retrieves the Estimated Time of Arrival for this waypoint, in UTC.
Input dialog with route print selection.
RoutePrintout(Route *route, const RoutePrintDlg &dlg, const int tz_selection)
Create route prinout.
void DrawPage(wxDC *dc, int page) override
Called by the print framework to draw the page.
Represents a navigational route in the navigation system.
double m_PlannedSpeed
Default planned speed for the route in knots.
wxString m_RouteStartString
Name or description of the route's starting point.
wxString m_RouteDescription
Additional descriptive information about the route.
double m_route_length
Total length of the route in nautical miles, calculated using rhumb line (Mercator) distances.
wxString m_RouteEndString
Name or description of the route's ending point.
wxString m_RouteNameString
User-assigned name for the route.
wxDateTime toUsrDateTime(const wxDateTime ts, const int format, const double lon)
Converts a timestamp from UTC to the user's preferred time format.
double toUsrDistance(double nm_distance, int unit)
Convert a distance from nautical miles (NMi) to user display units.
Navigation Utility Functions without GUI dependencies.
Generic, styled prit dialog.
OpenCPN Route table printout.
TCMgr * ptcmgr
Global instance.
Tide and Current Manager @TODO Add original author copyright.