OpenCPN Partial API docs
routeprintout.cpp
1 /***************************************************************************
2  *
3  * Project: OpenCPN
4  * Purpose: OpenCPN Route printout
5  * Author: Pavel Saviankou
6  *
7  ***************************************************************************
8  * Copyright (C) 2012 by David S. Register *
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  * This program is distributed in the hope that it will be useful, *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18  * GNU General Public License for more details. *
19  * *
20  * You should have received a copy of the GNU General Public License *
21  * along with this program; if not, write to the *
22  * Free Software Foundation, Inc., *
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24  **************************************************************************/
25 
26 #include <iostream>
27 
28 #include <wx/wxprec.h>
29 
30 #ifndef WX_PRECOMP
31 #include <wx/wx.h>
32 #endif // precompiled headers
33 #ifdef __WXMSW__
34 //#include "c:\\Program Files\\visual leak detector\\include\\vld.h"
35 #endif
36 
37 #include <wx/print.h>
38 #include <wx/printdlg.h>
39 #include <wx/artprov.h>
40 #include <wx/stdpaths.h>
41 #include <wx/intl.h>
42 #include <wx/listctrl.h>
43 #include <wx/aui/aui.h>
44 #include <wx/dialog.h>
45 #include <wx/progdlg.h>
46 #include <wx/brush.h>
47 #include <wx/colour.h>
48 
49 #include <wx/dialog.h>
50 
51 #include "navutil.h"
52 #include "dychart.h"
53 
54 #ifdef __WXMSW__
55 #include <stdlib.h>
56 #include <math.h>
57 #include <time.h>
58 #include <psapi.h>
59 #endif
60 
61 #ifndef __WXMSW__
62 #include <signal.h>
63 #include <setjmp.h>
64 #endif
65 #include "routeprintout.h"
66 
67 #include "printtable.h"
68 #include "model/wx28compat.h"
69 #include "model/track.h"
70 #include "model/route.h"
71 #include "gui_lib.h"
72 #include "model/navutil_base.h"
73 
74 #define PRINT_WP_NAME 0
75 #define PRINT_WP_POSITION 1
76 #define PRINT_WP_COURSE 2
77 #define PRINT_WP_DISTANCE 3
78 #define PRINT_WP_DESCRIPTION 4
79 
80 using namespace std;
81 
82 // Global print data, to remember settings during the session
83 extern wxPrintData* g_printData;
84 // Global page setup data
85 extern wxPageSetupData* g_pageSetupData;
86 
87 MyRoutePrintout::MyRoutePrintout(std::vector<bool> _toPrintOut, Route* route,
88  const wxString& title)
89  : MyPrintout(title), myRoute(route), toPrintOut(_toPrintOut) {
90  // Let's have at least some device units margin
91  marginX = 100;
92  marginY = 100;
93 
94  // Offset text from the edge of the cell (Needed on Linux)
95  textOffsetX = 5;
96  textOffsetY = 8;
97 
98  table.StartFillHeader();
99  // setup widths for columns
100 
101  table << _("Leg");
102 
103  if (toPrintOut[PRINT_WP_NAME]) {
104  table << _("To Waypoint");
105  }
106  if (toPrintOut[PRINT_WP_POSITION]) {
107  table << _("Position");
108  }
109  if (toPrintOut[PRINT_WP_COURSE]) {
110  table << _("Course");
111  }
112  if (toPrintOut[PRINT_WP_DISTANCE]) {
113  table << _("Distance");
114  }
115  if (toPrintOut[PRINT_WP_DESCRIPTION]) {
116  table << _("Description");
117  }
118 
119  table.StartFillWidths();
120 
121  table << 20; // "Leg" column
122 
123  // setup widths for columns
124  if (toPrintOut[PRINT_WP_NAME]) {
125  table << 40;
126  }
127  if (toPrintOut[PRINT_WP_POSITION]) {
128  table << 40;
129  }
130  if (toPrintOut[PRINT_WP_COURSE]) {
131  table << 40;
132  }
133  if (toPrintOut[PRINT_WP_DISTANCE]) {
134  table << 80;
135  }
136  if (toPrintOut[PRINT_WP_DESCRIPTION]) {
137  table << 100;
138  }
139 
140  table.StartFillData();
141 
142  for (int n = 1; n <= myRoute->GetnPoints(); n++) {
143  RoutePoint* point = myRoute->GetPoint(n);
144 
145  RoutePoint* pointm1 = NULL;
146  if (n - 1 >= 0) pointm1 = myRoute->GetPoint(n - 1);
147 
148  if (NULL == point) continue;
149 
150  wxString leg = _T("---");
151  if (n > 1) leg.Printf(_T("%d"), n - 1);
152 
153  string cell(leg.mb_str());
154 
155  table << cell;
156 
157  if (toPrintOut[PRINT_WP_NAME]) {
158  string cell(point->GetName().mb_str());
159  table << cell;
160  }
161  if (toPrintOut[PRINT_WP_POSITION]) {
162  wxString point_position = toSDMM(1, point->m_lat, false) + _T( "\n" ) +
163  toSDMM(2, point->m_lon, false);
164  string cell(point_position.mb_str());
165  table << cell;
166  }
167  if (toPrintOut[PRINT_WP_COURSE]) {
168  wxString point_course = "---";
169  if (pointm1) {
170  point_course = formatAngle(point->GetCourse());
171  }
172  table << point_course;
173  }
174  if (toPrintOut[PRINT_WP_DISTANCE]) {
175  wxString point_distance = _T("---");
176  if (n > 1)
177  point_distance.Printf(_T("%6.2f" + getUsrDistanceUnit()),
178  toUsrDistance(point->GetDistance()));
179  table << point_distance;
180  }
181  if (toPrintOut[PRINT_WP_DESCRIPTION]) {
182  table << point->GetDescription();
183  }
184  table << "\n";
185  }
186 }
187 
188 void MyRoutePrintout::GetPageInfo(int* minPage, int* maxPage, int* selPageFrom,
189  int* selPageTo) {
190  *minPage = 1;
191  *maxPage = numberOfPages;
192  *selPageFrom = 1;
193  *selPageTo = numberOfPages;
194 }
195 
196 void MyRoutePrintout::OnPreparePrinting() {
197  pageToPrint = 1;
198  wxDC* dc = GetDC();
199  wxFont routePrintFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
200  wxFONTWEIGHT_NORMAL);
201  dc->SetFont(routePrintFont);
202 
203  // Get the size of the DC in pixels
204  int w, h;
205  dc->GetSize(&w, &h);
206 
207  // We don't know before hand what size the Print DC will be, in pixels. Varies
208  // by host. So, if the dc size is greater than 1000 pixels, we scale
209  // accordinly.
210 
211  int maxX = wxMin(w, 1000);
212  int maxY = wxMin(h, 1000);
213 
214  // Calculate a suitable scaling factor
215  double scaleX = (double)(w / maxX);
216  double scaleY = (double)(h / maxY);
217 
218  // Use x or y scaling factor, whichever fits on the DC
219  double actualScale = wxMin(scaleX, scaleY);
220 
221  // Set the scale and origin
222  dc->SetUserScale(actualScale, actualScale);
223  dc->SetDeviceOrigin((long)marginX, (long)marginY);
224 
225  table.AdjustCells(dc, marginX, marginY);
226  numberOfPages = table.GetNumberPages();
227 }
228 
229 bool MyRoutePrintout::OnPrintPage(int page) {
230  wxDC* dc = GetDC();
231  if (dc) {
232  if (page <= numberOfPages) {
233  pageToPrint = page;
234  DrawPage(dc);
235  return true;
236  } else
237  return false;
238  } else
239  return false;
240 }
241 
242 void MyRoutePrintout::DrawPage(wxDC* dc) {
243  wxFont routePrintFont_bold(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
244  wxFONTWEIGHT_BOLD);
245  dc->SetFont(routePrintFont_bold);
246  wxBrush brush(wxColour(255, 255, 255), wxBRUSHSTYLE_TRANSPARENT);
247  dc->SetBrush(brush);
248 
249  int header_textOffsetX = 2;
250  int header_textOffsetY = 2;
251 
252  dc->DrawText(myRoute->m_RouteNameString, 150, 20);
253 
254  int currentX = marginX;
255  int currentY = marginY;
256  vector<PrintCell>& header_content = table.GetHeader();
257  for (size_t j = 0; j < header_content.size(); j++) {
258  PrintCell& cell = header_content[j];
259  dc->DrawRectangle(currentX, currentY, cell.GetWidth(), cell.GetHeight());
260  dc->DrawText(cell.GetText(), currentX + header_textOffsetX,
261  currentY + header_textOffsetY);
262  currentX += cell.GetWidth();
263  }
264 
265  wxFont routePrintFont_normal(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
266  wxFONTWEIGHT_NORMAL);
267  dc->SetFont(routePrintFont_normal);
268 
269  vector<vector<PrintCell> >& cells = table.GetContent();
270  currentY = marginY + table.GetHeaderHeight();
271  int currentHeight = 0;
272  for (size_t i = 0; i < cells.size(); i++) {
273  vector<PrintCell>& content_row = cells[i];
274  currentX = marginX;
275  for (size_t j = 0; j < content_row.size(); j++) {
276  PrintCell& cell = content_row[j];
277  if (cell.GetPage() == pageToPrint) {
278  wxRect r(currentX, currentY, cell.GetWidth(), cell.GetHeight());
279  dc->DrawRectangle(r);
280  r.Offset(textOffsetX, textOffsetY);
281  dc->DrawLabel(cell.GetText(), r);
282  currentX += cell.GetWidth();
283  currentHeight = cell.GetHeight();
284  }
285  }
286  currentY += currentHeight;
287  }
288 }
289 
290 // ---------- RoutePrintSelection dialof implementation
291 
296 IMPLEMENT_DYNAMIC_CLASS(RoutePrintSelection, wxDialog)
301 BEGIN_EVENT_TABLE(RoutePrintSelection, wxDialog)
302 EVT_BUTTON(ID_ROUTEPRINT_SELECTION_CANCEL,
303  RoutePrintSelection::OnRoutepropCancelClick)
304 EVT_BUTTON(ID_ROUTEPRINT_SELECTION_OK, RoutePrintSelection::OnRoutepropOkClick)
305 END_EVENT_TABLE()
306 
307 
312 
313 RoutePrintSelection::RoutePrintSelection(wxWindow* parent, Route* _route,
314  wxWindowID id, const wxString& caption,
315  const wxPoint& pos, const wxSize& size,
316  long style) {
317  route = _route;
318 
319  long wstyle = style;
320 
321  Create(parent, id, caption, pos, size, wstyle);
322  Centre();
323 }
324 
325 RoutePrintSelection::~RoutePrintSelection() {}
326 
331 bool RoutePrintSelection::Create(wxWindow* parent, wxWindowID id,
332  const wxString& caption, const wxPoint& pos,
333  const wxSize& size, long style) {
334  SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
335 
336 #ifdef __WXOSX__
337  style |= wxSTAY_ON_TOP;
338 #endif
339 
340  wxDialog::Create(parent, id, _("Print Route Selection"), pos, size, style);
341 
342  CreateControls();
343 
344  return TRUE;
345 }
346 
352  RoutePrintSelection* itemDialog1 = this;
353 
354  wxStaticBox* itemStaticBoxSizer3Static =
355  new wxStaticBox(itemDialog1, wxID_ANY, _("Elements to print..."));
356 
357  wxStaticBoxSizer* itemBoxSizer1 =
358  new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxVERTICAL);
359  itemDialog1->SetSizer(itemBoxSizer1);
360 
361  wxFlexGridSizer* fgSizer2;
362  fgSizer2 = new wxFlexGridSizer(5, 2, 0, 0);
363 
364  m_checkBoxWPName =
365  new wxCheckBox(itemDialog1, wxID_ANY, _("Name"), wxDefaultPosition,
366  wxDefaultSize, wxALIGN_LEFT);
367  m_checkBoxWPName->SetValue(true);
368  fgSizer2->Add(m_checkBoxWPName, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
369 
370  wxStaticText* label1 =
371  new wxStaticText(itemDialog1, wxID_ANY, _("Show Waypoint name."),
372  wxDefaultPosition, wxDefaultSize);
373  fgSizer2->Add(label1, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
374 
375  m_checkBoxWPPosition =
376  new wxCheckBox(itemDialog1, wxID_ANY, _("Position"), wxDefaultPosition,
377  wxDefaultSize, wxALIGN_LEFT);
378  m_checkBoxWPPosition->SetValue(true);
379  fgSizer2->Add(m_checkBoxWPPosition, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
380  wxStaticText* label2 =
381  new wxStaticText(itemDialog1, wxID_ANY, _("Show Waypoint position."),
382  wxDefaultPosition, wxDefaultSize);
383  fgSizer2->Add(label2, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
384 
385  m_checkBoxWPCourse =
386  new wxCheckBox(itemDialog1, wxID_ANY, _("Course"), wxDefaultPosition,
387  wxDefaultSize, wxALIGN_LEFT);
388  m_checkBoxWPCourse->SetValue(true);
389  fgSizer2->Add(m_checkBoxWPCourse, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
390  wxStaticText* label3 =
391  new wxStaticText(itemDialog1, wxID_ANY,
392  _("Show course from each Waypoint to the next one. "),
393  wxDefaultPosition, wxDefaultSize);
394  fgSizer2->Add(label3, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
395 
396  m_checkBoxWPDistanceToNext =
397  new wxCheckBox(itemDialog1, wxID_ANY, _("Distance"), wxDefaultPosition,
398  wxDefaultSize, wxALIGN_LEFT);
399  m_checkBoxWPDistanceToNext->SetValue(true);
400  fgSizer2->Add(m_checkBoxWPDistanceToNext, 0, wxALL | wxALIGN_CENTER_VERTICAL,
401  5);
402  wxStaticText* label4 =
403  new wxStaticText(itemDialog1, wxID_ANY,
404  _("Show Distance from each Waypoint to the next one."),
405  wxDefaultPosition, wxDefaultSize);
406  fgSizer2->Add(label4, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
407 
408  m_checkBoxWPDescription =
409  new wxCheckBox(itemDialog1, wxID_ANY, _("Description"), wxDefaultPosition,
410  wxDefaultSize, wxALIGN_LEFT);
411  m_checkBoxWPDescription->SetValue(true);
412  fgSizer2->Add(m_checkBoxWPDescription, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
413  wxStaticText* label5 =
414  new wxStaticText(itemDialog1, wxID_ANY, _("Show Waypoint description."),
415  wxDefaultPosition, wxDefaultSize);
416  fgSizer2->Add(label5, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
417 
418  itemBoxSizer1->Add(fgSizer2, 5, wxEXPAND, 5);
419 
420  wxBoxSizer* itemBoxSizer16 = new wxBoxSizer(wxHORIZONTAL);
421  itemBoxSizer1->Add(itemBoxSizer16, 0, wxALIGN_RIGHT | wxALL, 5);
422 
423  m_CancelButton =
424  new wxButton(itemDialog1, ID_ROUTEPRINT_SELECTION_CANCEL, _("Cancel"),
425  wxDefaultPosition, wxDefaultSize, 0);
426  itemBoxSizer16->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
427 
428  m_OKButton = new wxButton(itemDialog1, ID_ROUTEPRINT_SELECTION_OK, _("OK"),
429  wxDefaultPosition, wxDefaultSize, 0);
430  itemBoxSizer16->Add(m_OKButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
431  m_OKButton->SetDefault();
432 
433  SetColorScheme((ColorScheme)0);
434 }
435 
436 void RoutePrintSelection::SetColorScheme(ColorScheme cs) { DimeControl(this); }
437 
438 /*
439  * Should we show tooltips?
440  */
441 
442 bool RoutePrintSelection::ShowToolTips() { return TRUE; }
443 
444 void RoutePrintSelection::SetDialogTitle(const wxString& title) {
445  SetTitle(title);
446 }
447 
448 void RoutePrintSelection::OnRoutepropCancelClick(wxCommandEvent& event) {
449  Close(); // Hide();
450  event.Skip();
451 }
452 
453 void RoutePrintSelection::OnRoutepropOkClick(wxCommandEvent& event) {
454  std::vector<bool> toPrintOut;
455  toPrintOut.push_back(m_checkBoxWPName->GetValue());
456  toPrintOut.push_back(m_checkBoxWPPosition->GetValue());
457  toPrintOut.push_back(m_checkBoxWPCourse->GetValue());
458  toPrintOut.push_back(m_checkBoxWPDistanceToNext->GetValue());
459  toPrintOut.push_back(m_checkBoxWPDescription->GetValue());
460 
461  if (NULL == g_printData) {
462  g_printData = new wxPrintData;
463  g_printData->SetOrientation(wxPORTRAIT);
464  g_pageSetupData = new wxPageSetupDialogData;
465  }
466 
467  MyRoutePrintout* myrouteprintout1 =
468  new MyRoutePrintout(toPrintOut, route, _("Route Print"));
469 
470  wxPrintDialogData printDialogData(*g_printData);
471  printDialogData.EnablePageNumbers(true);
472 
473  wxPrinter printer(&printDialogData);
474  if (!printer.Print(this, myrouteprintout1, true)) {
475  if (wxPrinter::GetLastError() == wxPRINTER_ERROR) {
476  OCPNMessageBox(NULL,
477  _("There was a problem printing.\nPerhaps your current "
478  "printer is not set correctly?"),
479  _T( "OpenCPN" ), wxOK);
480  }
481  }
482 
483  Close();
484  event.Skip();
485 }
This class takes multilined string and modifies it to fit into given width for given device.
Definition: printtable.h:113
bool Create(wxWindow *parent, wxWindowID id=SYMBOL_ROUTEPRINT_SELECTION_IDNAME, const wxString &caption=SYMBOL_ROUTEPRINT_SELECTION_TITLE, const wxPoint &pos=SYMBOL_ROUTEPRINT_SELECTION_POSITION, const wxSize &size=SYMBOL_ROUTEPRINT_SELECTION_SIZE, long style=SYMBOL_ROUTEPRINT_SELECTION_STYLE)
Definition: route.h:75
General purpose GUI support.