1 /***************************************************************************
2  *
3  * Project:  OpenCPN
4  * Purpose:  OpenCPN Route printout
5  * Author:   Pavel Saviankou, Sean D'Epagnier
6  *
7  ***************************************************************************
8  *   Copyright (C) 2017 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 using namespace std;
28 
29 #include "wx/wxprec.h"
30 
31 #ifndef  WX_PRECOMP
32 #include "wx/wx.h"
33 #endif //precompiled headers
34 
35 #include "wx/print.h"
36 #include "wx/printdlg.h"
37 #include "wx/artprov.h"
38 #include "wx/stdpaths.h"
39 #include <wx/intl.h>
40 #include <wx/listctrl.h>
41 #include <wx/aui/aui.h>
42 #include <wx/dialog.h>
43 #include <wx/progdlg.h>
44 #include <wx/brush.h>
45 #include <wx/colour.h>
46 
47 
48 #include <wx/dialog.h>
49 #include "dychart.h"
50 
51 #ifdef __WXMSW__
52 #include <stdlib.h>
53 #include <math.h>
54 #include <time.h>
55 #include <psapi.h>
56 #endif
57 
58 #include "trackprintout.h"
59 #include "printtable.h"
60 #include "Track.h"
61 
62 enum {PRINT_POSITION, PRINT_DISTANCE, PRINT_BEARING, PRINT_TIME, PRINT_SPEED};
63 
64 // Global print data, to remember settings during the session
65 extern wxPrintData*     g_printData;
66 // Global page setup data
67 extern wxPageSetupData* g_pageSetupData;
68 
MyTrackPrintout(std::vector<bool> _toPrintOut,Track * track,OCPNTrackListCtrl * lcPoints,const wxString & title)69 MyTrackPrintout::MyTrackPrintout( std::vector<bool> _toPrintOut,
70                                   Track*            track,
71                                   OCPNTrackListCtrl *lcPoints,
72                                   const wxString   &title
73                                   ) : MyPrintout( title ),
74                                       myTrack( track ),
75                                       toPrintOut( _toPrintOut )
76 {
77     // Let's have at least some device units margin
78     marginX = 100;
79     marginY = 100;
80 
81     // Offset text from the edge of the cell (Needed on Linux)
82     textOffsetX = 5;
83     textOffsetY = 8;
84 
85     table.StartFillHeader();
86     // setup widths for columns
87 
88     table << (const char *)wxString(_("Leg")).mb_str();
89 
90     if ( toPrintOut[ PRINT_POSITION ] ) {
91         table << (const char *)wxString(_("Position")).mb_str();
92     }
93     if ( toPrintOut[ PRINT_BEARING ] ) {
94         table << (const char *)wxString(_("Course")).mb_str();
95     }
96     if ( toPrintOut[ PRINT_DISTANCE ] ) {
97         table << (const char *)wxString(_("Distance")).mb_str();
98     }
99     if ( toPrintOut[ PRINT_TIME ] ) {
100         table << (const char *)wxString(_("Time")).mb_str();
101     }
102     if ( toPrintOut[ PRINT_SPEED ] ) {
103         table << (const char *)wxString(_("Speed")).mb_str();
104     }
105 
106     table.StartFillWidths();
107 
108     table << 20;                // "Leg" column
109     // setup widths for columns
110     if ( toPrintOut[ PRINT_POSITION ] )
111         table << 80;
112     if ( toPrintOut[ PRINT_BEARING ] )
113         table << 40;
114     if ( toPrintOut[ PRINT_DISTANCE ] )
115         table << 40;
116     if ( toPrintOut[ PRINT_TIME ] )
117         table << 60;
118     if ( toPrintOut[ PRINT_SPEED ] )
119         table << 40;
120 
121     table.StartFillData();
122     for ( int n = 0; n <= myTrack->GetnPoints(); n++ ) {
123         table << lcPoints->OnGetItemText(n, 0); // leg
124 
125         if ( toPrintOut[ PRINT_POSITION ] ) {
126             // lat + lon
127             wxString pos = lcPoints->OnGetItemText(n, 3) + _T(" ") + lcPoints->OnGetItemText(n, 4);
128             table << pos;
129         }
130         if ( toPrintOut[ PRINT_BEARING ] )
131             table << lcPoints->OnGetItemText(n, 2); // bearing
132         if ( toPrintOut[ PRINT_DISTANCE ] )
133             table << lcPoints->OnGetItemText(n, 1); // distance
134         if ( toPrintOut[ PRINT_TIME ] )
135             table << lcPoints->OnGetItemText(n, 5); // time
136         if ( toPrintOut[ PRINT_SPEED ] )
137             table << lcPoints->OnGetItemText(n, 6); // speed
138         table << "\n";
139     }
140 }
141 
142 
GetPageInfo(int * minPage,int * maxPage,int * selPageFrom,int * selPageTo)143 void MyTrackPrintout::GetPageInfo( int* minPage, int* maxPage, int* selPageFrom, int* selPageTo )
144 {
145     *minPage     = 1;
146     *maxPage     = numberOfPages;
147     *selPageFrom = 1;
148     *selPageTo   = numberOfPages;
149 }
150 
151 
OnPreparePrinting()152 void MyTrackPrintout::OnPreparePrinting()
153 {
154     pageToPrint = 1;
155     wxDC*  dc = GetDC();
156     wxFont trackPrintFont( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
157     dc->SetFont( trackPrintFont );
158 
159     // Get the size of the DC in pixels
160     int w, h;
161     dc->GetSize( &w, &h );
162 
163     // We don't know before hand what size the Print DC will be, in pixels.  Varies by host.
164     // So, if the dc size is greater than 1000 pixels, we scale accordinly.
165 
166     int maxX = wxMin(w, 1000);
167     int maxY = wxMin(h, 1000);
168 
169     // Calculate a suitable scaling factor
170     double scaleX = ( double )( w / maxX );
171     double scaleY = ( double )( h / maxY );
172 
173     // Use x or y scaling factor, whichever fits on the DC
174     double actualScale = wxMin( scaleX, scaleY );
175 
176     // Set the scale and origin
177     dc->SetUserScale( actualScale, actualScale );
178     dc->SetDeviceOrigin( ( long )marginX, ( long )marginY );
179 
180     table.AdjustCells( dc, marginX, marginY );
181     numberOfPages = table.GetNumberPages();
182 }
183 
184 
OnPrintPage(int page)185 bool MyTrackPrintout::OnPrintPage( int page )
186 {
187     wxDC* dc = GetDC();
188     if( dc ) {
189         if( page <= numberOfPages ){
190             pageToPrint = page;
191             DrawPage( dc );
192             return true;
193         }
194         else
195             return false;
196     } else
197         return false;
198 
199 }
200 
DrawPage(wxDC * dc)201 void MyTrackPrintout::DrawPage( wxDC* dc )
202 {
203 
204 
205     wxFont trackPrintFont_bold( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD );
206     dc->SetFont( trackPrintFont_bold );
207     wxBrush brush( wxColour(255,255,255),  wxBRUSHSTYLE_TRANSPARENT );
208     dc->SetBrush( brush );
209 
210     int header_textOffsetX = 2;
211     int header_textOffsetY = 2;
212 
213     dc->DrawText( myTrack->GetName(),  150, 20 );
214 
215     int currentX = marginX;
216     int currentY = marginY;
217     vector< PrintCell >& header_content = table.GetHeader();
218     for ( size_t j = 0; j < header_content.size(); j++ ) {
219         PrintCell& cell = header_content[ j ];
220         dc->DrawRectangle( currentX, currentY, cell.GetWidth(), cell.GetHeight() );
221         dc->DrawText( cell.GetText(),  currentX +header_textOffsetX, currentY + header_textOffsetY );
222         currentX += cell.GetWidth();
223     }
224 
225     wxFont  trackPrintFont_normal( 10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
226     dc->SetFont( trackPrintFont_normal );
227 
228     vector< vector < PrintCell > > & cells = table.GetContent();
229     currentY = marginY + table.GetHeaderHeight();
230     int currentHeight = 0;
231     for ( size_t i = 0; i < cells.size(); i++ ) {
232         vector< PrintCell >& content_row = cells[ i ];
233         currentX = marginX;
234         for ( size_t j = 0; j < content_row.size(); j++ ) {
235             PrintCell& cell = content_row[ j ];
236             if ( cell.GetPage() == pageToPrint ) {
237                 wxRect r( currentX, currentY, cell.GetWidth(), cell.GetHeight() );
238                 dc->DrawRectangle( r );
239                 r.Offset( textOffsetX, textOffsetY );
240                 dc->DrawLabel(cell.GetText(), r);
241                 currentX     += cell.GetWidth();
242                 currentHeight = cell.GetHeight();
243             }
244         }
245         currentY += currentHeight;
246     }
247 }
248 
249 
250 // ---------- TrackPrintSelection dialof implementation
251 
IMPLEMENT_DYNAMIC_CLASS(TrackPrintSelection,wxDialog)252 IMPLEMENT_DYNAMIC_CLASS( TrackPrintSelection, wxDialog )
253 BEGIN_EVENT_TABLE( TrackPrintSelection, wxDialog )
254 EVT_BUTTON( ID_TRACKPRINT_SELECTION_CANCEL, TrackPrintSelection::OnTrackpropCancelClick )
255 EVT_BUTTON( ID_TRACKPRINT_SELECTION_OK, TrackPrintSelection::OnTrackpropOkClick )
256 END_EVENT_TABLE()
257 TrackPrintSelection::TrackPrintSelection()
258 {
259 }
260 
TrackPrintSelection(wxWindow * parent,Track * _track,OCPNTrackListCtrl * lcPoints,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)261 TrackPrintSelection::TrackPrintSelection( wxWindow*       parent,
262                                           Track*          _track,
263                                           OCPNTrackListCtrl *lcPoints,
264                                           wxWindowID      id,
265                                           const wxString& caption,
266                                           const wxPoint&  pos,
267                                           const wxSize&   size,
268                                           long            style )
269 {
270     track = _track;
271     m_lcPoints = lcPoints;
272 
273     long wstyle = style;
274 
275     Create( parent, id, caption, pos, size, wstyle );
276     Centre();
277 }
278 
279 
~TrackPrintSelection()280 TrackPrintSelection::~TrackPrintSelection()
281 {
282 }
283 
284 
285 /*!
286  * TrackProp creator
287  */
288 
Create(wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)289 bool TrackPrintSelection::Create( wxWindow* parent, wxWindowID id, const wxString& caption,
290                              const wxPoint& pos, const wxSize& size, long style )
291 {
292     SetExtraStyle( GetExtraStyle() | wxWS_EX_BLOCK_EVENTS );
293 
294 #ifdef __WXOSX__
295     style |= wxSTAY_ON_TOP;
296 #endif
297 
298     wxDialog::Create( parent, id, _("Print Track Selection"), pos, size, style );
299 
300     CreateControls();
301 
302     return TRUE;
303 }
304 
305 
306 /*!
307  * Control creation for TrackProp
308  */
309 
CreateControls()310 void TrackPrintSelection::CreateControls()
311 {
312     TrackPrintSelection* itemDialog1 = this;
313     wxStaticBox*         itemStaticBoxSizer3Static = new wxStaticBox( itemDialog1, wxID_ANY,
314                                                                       _( "Elements to print..." ) );
315     wxStaticBoxSizer* itemBoxSizer1 = new wxStaticBoxSizer( itemStaticBoxSizer3Static,  wxVERTICAL );
316     itemDialog1->SetSizer( itemBoxSizer1 );
317 
318     wxFlexGridSizer* fgSizer2;
319     fgSizer2 = new wxFlexGridSizer( 5, 2, 0, 0 );
320 
321     m_checkBoxPosition = new wxCheckBox( itemDialog1, wxID_ANY, _( "Position" ),
322                                          wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
323     m_checkBoxPosition->SetValue( true );
324     fgSizer2->Add( m_checkBoxPosition, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
325     wxStaticText* label2 = new  wxStaticText( itemDialog1, wxID_ANY, _( "Show Waypoint position." ), wxDefaultPosition, wxDefaultSize );
326     fgSizer2->Add( label2, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
327 
328     m_checkBoxCourse = new wxCheckBox( itemDialog1, wxID_ANY, _( "Course" ),
329                                        wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
330     m_checkBoxCourse->SetValue( true );
331     fgSizer2->Add( m_checkBoxCourse, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
332     wxStaticText* label3 = new  wxStaticText( itemDialog1, wxID_ANY, _( "Show course from each Waypoint to the next one. " ), wxDefaultPosition, wxDefaultSize );
333     fgSizer2->Add( label3, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
334 
335     m_checkBoxDistance = new wxCheckBox( itemDialog1, wxID_ANY, _( "Distance" ),
336                                          wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
337     m_checkBoxDistance->SetValue( true );
338     fgSizer2->Add( m_checkBoxDistance, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
339     wxStaticText* label4 = new  wxStaticText( itemDialog1, wxID_ANY, _( "Show Distance from each Waypoint to the next one." ), wxDefaultPosition, wxDefaultSize );
340     fgSizer2->Add( label4, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
341 
342     m_checkBoxTime = new wxCheckBox( itemDialog1, wxID_ANY, _( "Time" ),
343                                      wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
344     m_checkBoxTime->SetValue( true );
345     fgSizer2->Add( m_checkBoxTime, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
346     wxStaticText* label5 = new  wxStaticText( itemDialog1, wxID_ANY, _( "Show Time." ), wxDefaultPosition, wxDefaultSize );
347     fgSizer2->Add( label5, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
348 
349     m_checkBoxSpeed = new wxCheckBox( itemDialog1, wxID_ANY, _( "Speed" ),
350                                       wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT );
351     m_checkBoxSpeed->SetValue( true );
352     fgSizer2->Add( m_checkBoxSpeed, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
353     wxStaticText* label6 = new  wxStaticText( itemDialog1, wxID_ANY, _( "Show Speed." ), wxDefaultPosition, wxDefaultSize );
354     fgSizer2->Add( label6, 1, wxALL | wxALIGN_CENTER_VERTICAL, 5 );
355 
356     itemBoxSizer1->Add( fgSizer2, 5, wxEXPAND, 5 );
357 
358     wxBoxSizer* itemBoxSizer16 = new wxBoxSizer( wxHORIZONTAL );
359     itemBoxSizer1->Add( itemBoxSizer16, 0, wxALIGN_RIGHT | wxALL, 5 );
360 
361     m_CancelButton = new wxButton( itemDialog1, ID_TRACKPRINT_SELECTION_CANCEL, _( "Cancel" ), wxDefaultPosition,
362                                    wxDefaultSize, 0 );
363     itemBoxSizer16->Add( m_CancelButton, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
364 
365     m_OKButton = new wxButton( itemDialog1, ID_TRACKPRINT_SELECTION_OK, _( "OK" ), wxDefaultPosition,
366                                wxDefaultSize, 0 );
367     itemBoxSizer16->Add( m_OKButton, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
368     m_OKButton->SetDefault();
369 
370     SetColorScheme( ( ColorScheme )0 );
371 }
372 
373 
SetColorScheme(ColorScheme cs)374 void TrackPrintSelection::SetColorScheme( ColorScheme cs )
375 {
376     DimeControl( this );
377 }
378 
379 
380 /*
381  * Should we show tooltips?
382  */
383 
ShowToolTips()384 bool TrackPrintSelection::ShowToolTips()
385 {
386     return TRUE;
387 }
388 
389 
SetDialogTitle(const wxString & title)390 void TrackPrintSelection::SetDialogTitle(const wxString & title)
391 {
392     SetTitle( title );
393 }
394 
395 
OnTrackpropCancelClick(wxCommandEvent & event)396 void TrackPrintSelection::OnTrackpropCancelClick( wxCommandEvent& event )
397 {
398     Close(); //Hide();
399     event.Skip();
400 }
401 
402 
OnTrackpropOkClick(wxCommandEvent & event)403 void TrackPrintSelection::OnTrackpropOkClick( wxCommandEvent& event )
404 {
405     std::vector<bool> toPrintOut;
406     toPrintOut.push_back( m_checkBoxPosition->GetValue() );
407     toPrintOut.push_back( m_checkBoxCourse->GetValue() );
408     toPrintOut.push_back( m_checkBoxDistance->GetValue() );
409     toPrintOut.push_back( m_checkBoxTime->GetValue() );
410     toPrintOut.push_back( m_checkBoxSpeed->GetValue() );
411 
412 
413     if ( NULL == g_printData ) {
414         g_printData = new wxPrintData;
415         g_printData->SetOrientation( wxPORTRAIT );
416         g_pageSetupData = new wxPageSetupDialogData;
417     }
418 
419     MyTrackPrintout*  mytrackprintout1 = new MyTrackPrintout( toPrintOut, track, m_lcPoints, _( "Track Print" ) );
420 
421     wxPrintDialogData printDialogData( *g_printData );
422     printDialogData.EnablePageNumbers( true );
423 
424     wxPrinter printer( &printDialogData );
425     if ( !printer.Print( this, mytrackprintout1, true ) ) {
426         if ( wxPrinter::GetLastError() == wxPRINTER_ERROR ) {
427             OCPNMessageBox(
428                 NULL,
429                 _( "There was a problem printing.\nPerhaps your current printer is not set correctly?" ),
430                 _T( "OpenCPN" ), wxOK );
431         }
432     }
433 
434     Close(); //Hide();
435     event.Skip();
436 }
437