OpenCPN Partial API docs
Loading...
Searching...
No Matches
track_printout.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2017 by David S. Register *
3 * Copyright (C) 2025 by NoCodeHummel *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
17 **************************************************************************/
18
25#include <iostream>
26
27#ifdef __WXMSW__
28#include <stdlib.h>
29#include <math.h>
30#include <time.h>
31#include <psapi.h>
32#endif
33
34#include <wx/wxprec.h>
35#ifndef WX_PRECOMP
36#include <wx/wx.h>
37#endif
38
39#include "gl_headers.h" // Must be included before anything using GL stuff
40
41#include <wx/aui/aui.h>
42#include <wx/brush.h>
43#include <wx/colour.h>
44#include <wx/dialog.h>
45#include <wx/intl.h>
46#include <wx/listctrl.h>
47#include <wx/printdlg.h>
48#include <wx/print.h>
49#include <wx/statline.h>
50#include <wx/stdpaths.h>
51
52#include "track_printout.h"
53
54#include "libgui/button_switch.h"
55
56#include "model/track.h"
57
58#include "dychart.h"
59#include "printtable.h"
60
61// Make _() return std::string instead of wxString;
62#undef _
63#if wxCHECK_VERSION(3, 2, 0)
64#define _(s) wxGetTranslation(wxASCII_STR(s)).ToStdString()
65#else
66#define _(s) wxGetTranslation((s)).ToStdString()
67#endif
68
69using namespace std;
70
71static const std::unordered_map<TrackPrintOptions, std::string> kLabelByOption =
72 {{TrackPrintOptions::kTrackPosition, _("Print Track Position")},
73 {TrackPrintOptions::kTrackCourse, _("Print Track Course")},
74 {TrackPrintOptions::kTrackDistance, _("Print Track Distance")},
75 {TrackPrintOptions::kTrackTime, _("Print Track Time")},
76 {TrackPrintOptions::kTrackSpeed, _("Print Track Speed")}};
77
78namespace {
79
80class ButtonSizer : public wxStdDialogButtonSizer {
81public:
82 explicit ButtonSizer(wxWindow* parent) : wxStdDialogButtonSizer() {
83 auto ok_btn = new wxButton(parent, wxID_OK, _("Print..."));
84 AddButton(ok_btn);
85 AddButton(new wxButton(parent, wxID_CANCEL));
86 SetAffirmativeButton(ok_btn);
87 Realize();
88 }
89};
90
91} // namespace
92
93TrackPrintDlg::TrackPrintDlg(wxWindow* parent)
94 : wxDialog(parent, wxID_ANY, _("Print track")) {
95 auto grid = new wxFlexGridSizer(2);
96 auto flags = wxSizerFlags().Border();
97 for (auto& [option, label] : kLabelByOption) {
98 grid->Add(new wxStaticText(this, wxID_ANY, label), flags.Expand());
99 int id = wxWindow::NewControlId();
100 grid->Add(new SwitchButton(this, id, true), flags);
101 IdByOption[option] = id;
102 }
103 auto vbox = new wxBoxSizer(wxVERTICAL);
104 vbox->Add(grid, wxSizerFlags(1));
105 vbox->Add(new wxStaticLine(this, wxID_ANY), wxSizerFlags().Expand());
106 vbox->Add(new ButtonSizer(this), flags);
107 SetSizer(vbox);
108 wxDialog::Fit();
109
110 Bind(wxEVT_CLOSE_WINDOW, [&](wxCloseEvent&) { Destroy(); });
111}
112
113bool TrackPrintDlg::IsEnabled(TrackPrintOptions option) const {
114 auto found = IdByOption.find(option);
115 assert(found != IdByOption.end() && "Illegal option");
116 int id = 0;
117 try {
118 id = IdByOption.at(option);
119 } catch (std::out_of_range&) {
120 assert(false && "No id for button");
121 }
122 auto* btn = dynamic_cast<SwitchButton*>(wxWindow::FindWindow(id));
123 assert(btn && "Could not look up button");
124 return btn->GetValue();
125}
126
128 const TrackPrintDlg& dlg)
129 : BasePrintout(_("Track Print")), m_track(track) {
130 // Offset text from the edge of the cell (Needed on Linux)
131 m_text_offset_x = 5;
132 m_text_offset_y = 8;
133
134 // setup widths for columns
135 m_table.StartFillHeader();
136
137 m_table << _("Leg");
138
139 if (dlg.IsEnabled(TrackPrintOptions::kTrackPosition)) {
140 m_table << _("Position");
141 }
142 if (dlg.IsEnabled(TrackPrintOptions::kTrackCourse)) {
143 m_table << _("Course");
144 }
145 if (dlg.IsEnabled(TrackPrintOptions::kTrackDistance)) {
146 m_table << _("Distance");
147 }
148 if (dlg.IsEnabled(TrackPrintOptions::kTrackTime)) {
149 m_table << _("Time");
150 }
151 if (dlg.IsEnabled(TrackPrintOptions::kTrackSpeed)) {
152 m_table << _("Speed");
153 }
154
155 m_table.StartFillWidths();
156
157 m_table << 20; // "Leg" column
158 // setup widths for columns
159 if (dlg.IsEnabled(TrackPrintOptions::kTrackPosition)) m_table << 80;
160 if (dlg.IsEnabled(TrackPrintOptions::kTrackCourse)) m_table << 40;
161 if (dlg.IsEnabled(TrackPrintOptions::kTrackDistance)) m_table << 40;
162 if (dlg.IsEnabled(TrackPrintOptions::kTrackTime)) m_table << 60;
163 if (dlg.IsEnabled(TrackPrintOptions::kTrackSpeed)) m_table << 40;
164
165 m_table.StartFillData();
166 for (int n = 0; n < m_track->GetnPoints(); n++) {
167 m_table << lcPoints->OnGetItemText(n, 0); // leg
168
169 if (dlg.IsEnabled(TrackPrintOptions::kTrackPosition)) {
170 m_table << lcPoints->OnGetItemText(n, 3) + _(" ") +
171 lcPoints->OnGetItemText(n, 4); // position
172 }
173 if (dlg.IsEnabled(TrackPrintOptions::kTrackCourse))
174 m_table << lcPoints->OnGetItemText(n, 2); // bearing
175 if (dlg.IsEnabled(TrackPrintOptions::kTrackDistance))
176 m_table << lcPoints->OnGetItemText(n, 1); // distance
177 if (dlg.IsEnabled(TrackPrintOptions::kTrackTime))
178 m_table << lcPoints->OnGetItemText(n, 5); // time
179 if (dlg.IsEnabled(TrackPrintOptions::kTrackSpeed))
180 m_table << lcPoints->OnGetItemText(n, 6); // speed
181 m_table << "\n";
182 }
183}
184
185void TrackPrintout::OnPreparePrinting() {
186 wxDC* dc = GetDC();
187 wxFont trackPrintFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
188 wxFONTWEIGHT_NORMAL);
189 dc->SetFont(trackPrintFont);
190
191 // Get the size of the DC in pixels
192 int w, h;
193 dc->GetSize(&w, &h);
194
195 // We don't know before hand what size the Print DC will be, in pixels. Varies
196 // by host. So, if the dc size is greater than 1000 pixels, we scale
197 // accordinly.
198 int max_x = wxMin(w, 1000);
199 int max_y = wxMin(h, 1000);
200
201 // Calculate a suitable scaling factor
202 double scale_x = (double)(w / max_x);
203 double scale_y = (double)(h / max_y);
204
205 // Use x or y scaling factor, whichever fits on the DC
206 double actual_scale = wxMin(scale_x, scale_y);
207
208 // Set the scale and origin
209 dc->SetUserScale(actual_scale, actual_scale);
210 dc->SetDeviceOrigin((long)m_margin_x, (long)m_margin_y);
211
212 m_table.AdjustCells(dc, m_margin_x, m_margin_y);
213 m_pages = m_table.GetNumberPages();
214}
215
216void TrackPrintout::DrawPage(wxDC* dc, int page) {
217 wxFont trackPrintFont_bold(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
218 wxFONTWEIGHT_BOLD);
219 dc->SetFont(trackPrintFont_bold);
220 wxBrush brush(wxColour(255, 255, 255), wxBRUSHSTYLE_TRANSPARENT);
221 dc->SetBrush(brush);
222
223 int header_text_offset_x = 2;
224 int header_text_offset_y = 2;
225
226 dc->DrawText(m_track->GetName(), 150, 20);
227
228 int current_x = m_margin_x;
229 int current_y = m_margin_y;
230 vector<PrintCell>& header_content = m_table.GetHeader();
231 for (size_t j = 0; j < header_content.size(); j++) {
232 PrintCell& cell = header_content[j];
233 dc->DrawRectangle(current_x, current_y, cell.GetWidth(), cell.GetHeight());
234 dc->DrawText(cell.GetText(), current_x + header_text_offset_x,
235 current_y + header_text_offset_y);
236 current_x += cell.GetWidth();
237 }
238
239 wxFont trackPrintFont_normal(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
240 wxFONTWEIGHT_NORMAL);
241 dc->SetFont(trackPrintFont_normal);
242
243 vector<vector<PrintCell> >& cells = m_table.GetContent();
244 current_y = m_margin_y + m_table.GetHeaderHeight();
245 int current_height = 0;
246 for (size_t i = 0; i < cells.size(); i++) {
247 vector<PrintCell>& content_row = cells[i];
248 current_x = m_margin_x;
249 for (size_t j = 0; j < content_row.size(); j++) {
250 PrintCell& cell = content_row[j];
251 if (cell.GetPage() == page) {
252 wxRect r(current_x, current_y, cell.GetWidth(), cell.GetHeight());
253 dc->DrawRectangle(r);
254 r.Offset(m_text_offset_x, m_text_offset_y);
255 dc->DrawLabel(cell.GetText(), r);
256 current_x += cell.GetWidth();
257 current_height = cell.GetHeight();
258 }
259 }
260 current_y += current_height;
261 }
262}
Application print support.
This class takes multilined string and modifies it to fit into given width for given device.
Definition printtable.h:106
On/Off switch button.
Input dialog with track print selection.
TrackPrintout(Track *track, OCPNTrackListCtrl *lcPoints, const TrackPrintDlg &dlg)
Create track printout.
void DrawPage(wxDC *dc, int page) override
Called by the print framework to draw the page.
Represents a track, which is a series of connected track points.
Definition track.h:117
Platform independent GL includes.
OpenCPN Route table printout.
Recorded track abstraction.
Track print dialog.